一、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 = 1
>>> c.x
1
>>> c.size
1
>>> del c.x
>>> c.size
Traceback (most recent call last):
File "<pyshell#18>", line 1, in <module>
c.size
AttributeError: 'C' object has no attribute 'size'
>>>
二、属性访问的魔法方法
__getattr__(self, name):定义当用户师徒获取一个不存在的属性时的行为
__getattribute__(self, name):定义当该类的属性被访问时的行为
__setattr__(self, name ,value):定义当一个属性被设置时的行为
__delattr__(self, name):定义当一个属性被删除时的行为
>>> del c.x
>>> class C:
def __getattribute__(self, name):
print('getattribute')
return super().__getattribute__(name)
def __getattr__(self, name):
print('getattr')
def __setattr__(self, name ,value):
print('setattr')
super().__setattr__(name, value)
def __delattr__(self, name):
print('delattr')
super().__delattr__(name)
>>> c = C()
>>> c.x
getattribute
getattr
>>> c.x = 1
setattr
>>> c.x
getattribute
1
>>> del c.x
delattr
>>>
三、练习:
写一个矩形类,默认有宽和高两个属性;
如果为一个叫square的属性赋值,那么说明这是一个正方形,值就是正方形的边长,此时宽和高都应该等于边长
1.死循环陷阱:
class Rectangle:
def __init__(self, width = 0, height = 0):
self.height = height
self.width = width
def __setattr__(self, name, value):
if name == 'square':
self.width = value
self.height = value
else:
self.name = value
def getArea(self):
return self.width *self.height
分析:初始化时self.height self.width两次赋值 调用__setattr__方法,跳入else语句,self.value = name语句继续赋值,调用__setattr__函数,进入死循环
改正:
class Rectangle:
def __init__(self, width = 0, height = 0):
self.height = height
self.width = width
def __setattr__(self, name, value):
if name == 'square':
self.width = value
self.height = value
else:
super().__setattr__(name, value)
def getArea(self):
return self.width *self.height
分析:__setattr__ 内重写赋值时,使用super().__setattr__(self, name, value) ,即使用基类的__setattr__方法进行赋值