Python学习Day17
属性访问
回顾:通过几个BIF适当地去访问属性
>>> class C:
def __init__(self):
self.x = 'Python'
>>> c = C()
>>> c.x
'Python'
>>> getattr(c,'x','木有这个属性')
'Python'
>>> getattr(c,'y','木有这个属性')
'木有这个属性'
>>>
>>> class A:
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)
>>> a = A()
>>> a.x
10
>>> a.x = 1
>>> a.x
1
>>> del a.x
>>> a.x
Traceback (most recent call last):
File "<pyshell#27>", line 1, in <module>
a.x
File "<pyshell#21>", line 5, in getSize
return self.size
AttributeError: 'A' object has no attribute 'size'
属性访问相应的魔法方法
-
_ _ getattr_ _ (self,name) 定义当用户试图获取一个不存在的属性时的行为 -
_ _ getattribute_ _ (self,name) 定义当该类的属性被访问时的方法 -
_ _ setattr_ _ (self,name,value) 定义当一个属性被设置的行为 -
_ _ delattr_ _ (self,name) 定义当一个属性被删除时的行为
>>> class C:
def __getattribute__(self,name):
print('getattribute')
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')
>>> c = C()
>>> c.x
getattribute
getattr
>>>
>>> c.x = 1
setattr
>>> c.x
getattribute
1
>>> del c.x
delattr
值得注意的是,这几个魔法方法在书写时会存在一个死循环陷阱
练习:
写一个矩形类,默认有宽(width)和高(height)两个属性;如果为一个叫square的属性赋值,那么说明这是一个正方形,此时值就是正方形的边长,高和宽都等于边长
class Rectangle:
def __init__(self,width=0,height=0):
self.width = width
self.height = height
def __setattr__(self,name,value):
if name == 'squarre':
self.width = value
self.height =value
else:
def getArea(self):
return self.width * self.height
按照上面代码运行程序后,则会出现死循环(无限递归)
解决方法
1.用super()来调用基类的setattr()方法,那么这样就依赖基类的方法来是实现赋值:
else:
super().__setattr(name,value)
2.给特殊属性_ _ dict_ _赋值,它的作用是以字典的形式显示出当前对象的所有属性以及相应的值
else:
self.__dict__[name] = value
描述符(Property原理)
描述符就是将某种特殊类型的类的实例指派给另一个类的属性
特殊的类:至少实现以下三个方法中的一个
-
_ _ get _ _(self, instance, owner) 用于访问属性,它返回属性的值 -
_ _ set _ _(self, instance, value) 将在属性分配操作中调用,不返回任何内容 -
_ _ delete _ _(self, instance) 控制删除操作,不返回任何内容
>>> class MyDecription:
def __get__(self, instance, owner):
print("getting...", self, instance, owner)
def __set__(self, instance, value):
print("setting...", self, instance, value)
def __delete__(self, instance):
print("deleting...", self, instance)
>>> class Test:
x = MyDecription()
>>>
>>>
>>> test = Test()
>>> test.x
getting... <__main__.MyDecription object at 0x00000273C5D66A90> <__main__.Test object at 0x00000273C5D511F0> <class '__main__.Test'>
>>>
>>> test
<__main__.Test object at 0x00000273C5D511F0>
>>> Test
<class '__main__.Test'>
>>> test.x = 'Python'
setting... <__main__.MyDecription object at 0x00000273C5D66A90> <__main__.Test object at 0x00000273C5D511F0> Python
>>> del test.x
deleting... <__main__.MyDecription object at 0x00000273C5D66A90> <__main__.Test object at 0x00000273C5D511F0>
Property其实就是一个描述符类
定义一个属于自己的MyProperty类
>>> class MyProperty:
def __init__(self, fget=None, fset=None, fdel=None):
self.fget = fget
self.fset = fset
self.fdel = fdel
def __get__(self, instance, owner):
return self.fget(instance)
def __set__(self, instance, value):
self.fget(instance , value)
def __delete__(self, instance):
self.fdel(instance)
>>> class C:
def __init__(self):
self._x = None
def getX(self):
return self._x
def setX(self,value):
self._x = value
def delX(self):
del self._x
x = MyProperty(getX, setX, delX)
|