通常可以通过点(.)操作符的形式去访问对象的属性,也可以通过BIF适当地去访问属性,看个例子吧

>>> class A():
def __init__(self):
self.x = 'XYZ-xyz' >>> a = A()
>>> a.x
'XYZ-xyz'
>>> getattr(a,'x','没有这个属性')
'XYZ-xyz'
>>> getattr(a,'z','没有这个属性')
'没有这个属性'
>>> setattr(a,'z','red')
>>> getattr(a,'z','red')
'red'
>>> delattr(a,'x')
>>> a.x
Traceback (most recent call last):
File "<pyshell#12>", line , in <module>
a.x
AttributeError: 'A' object has no attribute 'x'

在来介绍一个property()函数的用法,这个property()使我们可以用属性去访问属性,还是会来看个例子

>>> class C():
def __init__(self,size = 10):
self.size = size
def getsize(self):
return self.size
def setsize(self,value):
self.size = value
def delsize(self):
del self.size
x = property(getsize,setsize,delsize) >>> c = C()
>>> c.x
10
>>> c.x = 12
>>> c.x
12
>>> c.size
12
>>> del c.x
>>> c.size
Traceback (most recent call last):
File "<pyshell#30>", line 1, in <module>
c.size
AttributeError: 'C' object has no attribute 'size'

关于属性访问,肯定也有相应的魔法方法来管理。通过对这些魔法方法的重写,照样可以随心所欲控制对象的属性访问。

来介绍下属性相关的魔法方法:

魔法方法 含义
__getattr__(self,name) 定义当用户试图获取一个不存在的属性十的行为
__getattribute__(self,name) 定义当该类的属性被访问时的行为
__setattr__(self,name) 定义当一个属性被设置时的行为
__delattr__(self,name) 定义当一个属性被删除时的行为

好了,我们先来做个测试:

>>> class A():
def __getattribute__(self,name):
print('getattribute')
#使用super()调用object基类__getattribut__()方法
return super().__getattribute__(name)
def __setattr__(self,name,value):
print('setattr')
super().__setattr__(name,value)
def __delattr__(self,name):
print('delattr')
super().__delattr__(name)
def __getattr__(self,name):
print('getattr') >>> a = A()
>>> a.x
getattribute
getattr
>>> a.x = 1
setattr
>>> a.x
getattribute
1
>>> del a.x
delattr
>>> setattr(a,'y','yellow')
setattr

这几个魔法方法在使用的时候要注意,防止进入死循环陷阱,下面通过实例来说明,写一个矩形类(Rectangle),默认有宽(width)和高(height)两个属性;如果为一个叫square的属性赋值,那么说明这是一个正方形,值就是正方形的边长,此时高宽都应该等于边长

>>> class Rectangle():
def __init__(self,width = 0,height = 0):
self.width = width
self.height = height
def __setattr__(self,key,value):
if key == 'square':
self.width = value
self.height = value
else:
self.key = value
def getArea(self):
return self.width *self.height >>> r1 = Rectangle(4,5)
Traceback (most recent call last):
File "<pyshell#65>", line 1, in <module> r1 = Rectangle(4,5)
File "<pyshell#64>", line 3, in __init__ self.width = width
File "<pyshell#64>", line 10, in __setattr__ self.key = value
File "<pyshell#64>", line 10, in __setattr__ self.key = value
File "<pyshell#64>", line 10, in __setattr__ self.key = value
[Previous line repeated 325 more times]
File "<pyshell#64>", line 6, in __setattr__ if key == 'square':
RecursionError: maximum recursion depth exceeded in comparison

出现这个循环的原因在于调用了__init__()方法,在这里给self.width和self.height分别初始化赋值。一旦发生赋值操作就会自动触发__setattr__()魔法方法,width和height两个属性被赋值,于是执行了else的下边的语句,就又变成了self.width=value,那么久相当于又触发了__setattr__()魔法方法,造成了死循环。

解决方法一,就是和刚才的一样,使用super()来调用基类的__setattr__(),那么这样就依赖基类的方法来实现赋值:

>>> class Rectangle():
def __init__(self,width = 0,height = 0):
self.width = width
self.height = height
def __setattr__(self,key,value):
if key == 'square':
self.width = value
self.height = value
else:
super().__setattr__(key,value)
def getArea(self):
return self.width *self.height >>> r1 = Rectangle(4,5)
>>> r1.getArea()
20
>>> r1.square = 10
>>> r1.getArea()
100

解决方法二:给特殊属性__dict__赋值。对象有一个特殊的属性,__dict__,它的作用是以字典的形式显示出当前对象的所有属性以及相对于的值。

调用死循环的类

>>> r1.__dict__
{'width': 10, 'height': 10}
>>> class Rectangle():
def __init__(self,width = 0,height = 0):
self.width = width
self.height = height
def __setattr__(self,key,value):
if key == 'square':
self.width = value
self.height = value
     else:
       self.__dict__[name] = value

>>> r1 = Rectangle(4,5)

python_魔法方法(四):属性访问的更多相关文章

  1. Python魔法方法之属性访问 ( __getattr__, __getattribute__, __setattr__, __delattr__ )

    通常情况下,我们在访问类或者实例对象的时候,会牵扯到一些属性访问的魔法方法,主要包括: ① __getattr__(self, name): 访问不存在的属性时调用 ② __getattribute_ ...

  2. 零基础学习python_魔法方法(41-48课)(迭代器)

    接下来这个为啥要叫魔法方法呢,额,这个嘛我是跟小甲鱼的视频取的名字一样的,因为会讲比较多杂的东西,有... 魔法方法详细阅读地址:http://bbs.fishc.com/thread-48793-1 ...

  3. 【python学习笔记】9.魔法方法、属性和迭代器

    [python学习笔记]9.魔法方法.属性和迭代器 魔法方法:xx, 收尾各有两个下划线的方法 __init__(self): 构造方法,创建对象时候自动执行,可以为其增加参数, 父类构造方法不会被自 ...

  4. ie8 报错:意外地调用了方法或属性访问

    在某场景中一句简单的js: $("#changeOption").text("增加"); 在 IE8 下面报错:'意外地调用了方法或属性访问' 改成:$(&qu ...

  5. python基础教程_学习笔记11:魔法方法、属性和迭代器

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/signjing/article/details/31417309 魔法方法.属性和迭代器 在pyth ...

  6. python学习笔记之七:魔法方法,属性

    在python中,有的名称会在前面和后面加上两个下划线,由这些名字组成的集合所包含的方法称为魔法方法(或者是特殊方法).如果对象实现了这些方法中的某一个,那么这个方法会在特殊的情况下(确切地说是根据名 ...

  7. 《Python基础教程(第二版)》学习笔记 -> 第九章 魔法方法、属性和迭代器

    准备工作 >>> class NewStyle(object): more_code_here >>> class OldStyle: more_code_here ...

  8. 【Python045-魔法方法:属性访问】

    一.属性的几种访问方式 1.类.属性名 >>> class C: def __init__(self): self.x = 'X-man' >>> c = C() ...

  9. python_魔法方法(五):描述符和定制序列

    描述符(property的原理) 描述符(descripto),用一句话来解释,描述符就是某种特殊的类的实例指派给另一个类的属性.那么什么是特殊类型的类呢?就是至少要在这个类中定义__get__(). ...

随机推荐

  1. BZOJ1707:[Usaco2007 Nov]tanning分配防晒霜

    我对贪心的理解:https://www.cnblogs.com/AKMer/p/9776293.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ...

  2. 洛谷【P1480】A/B Problem

    题目传送门:https://www.luogu.org/problemnew/show/P1480 高精除低精板子题,灵性地回忆一下小学时期列竖式的草稿纸即可. 时间复杂度:\(O(len)\) 空间 ...

  3. MySQL数据库服务器参数优化mycnf,16G内存8核CPU,

    业务场景: 后台支持手机在线更新系统,db服务器内存16G,8核,dell的pc服务器. qps: 200个左右 tps: 1个左右 一分钟50几个 sort_buffer_size = 32M 大了 ...

  4. Poj 1887 Testing the CATCHER(LIS)

    一.Description A military contractor for the Department of Defense has just completed a series of pre ...

  5. HDOJ1242(延时迷宫BFS+优先队列)

    Rescue Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  6. excel2003, 2007最大行列、sheet数

    1.excel2003版本一个工作表最多可有65536行,行用数字1—65536表示;     256列,列用英文字母A—Z,AA—AZ,BA—BZ,……,IA—IV表示.2.一个工作簿中最多含有25 ...

  7. Angular14 Angular相关命令

    1 创建相关 1.1 创建项目 ng new 项目名  ->  创建新项目 ng new 项目名 --skip-install  -> 不进行模块安装  ng new 项目名 -si ng ...

  8. RecommenderFilterSalaryResult

    package org.andy.mymahout.recommendation.job; import java.io.BufferedReader; import java.io.File; im ...

  9. Luogu 2258 [NOIP2014] 子矩阵

    被普及组虐了,感觉

  10. Entity Framework Code-First(9.2):DataAnnotations - TimeStamp Attribute

    DataAnnotations - TimeStamp Attribute: TimeStamp attribute can be applied to only one byte array pro ...