Python--27 魔法方法 属性访问
属性访问
>>> class C: ... def __init__(self): ... self.x = 'X-man' ... >>> c = C() >>> c.x 'X-man' >>> getattr(c,'x','没有这个属性') 'X-man' >>> getattr(c,'y','没有这个属性') '没有这个属性' >>> 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 = 1 >>> c.x 1 >>> c.size 1 >>> del c.x >>> c.size Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'C' 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 __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 >>> del c.x delattr
练习要求
写一个矩形类,默认有宽和高两个属性
如果为一个叫square的属性赋值,那么说明这是一个正方形,值就是正方形的边长,此时宽和高都应该等于边长。
>>> class Rectangle: ... def __init__(self, width = 0, height = 0): ... self.width = width ... self.height = height ... 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 ... >>> r = Rectangle() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in __init__ File "<stdin>", line 10, in __setattr__ File "<stdin>", line 10, in __setattr__ File "<stdin>", line 10, in __setattr__ [Previous line repeated 327 more times] RecursionError: maximum recursion depth exceeded
两种方法
方法一:调用基类的__setattr__
方法二:__dice__[name]
>>> r = Rectangle() >>> r = Rectangle(4,5) >>> r.getArea() 20 >>> r1.squre = 10 >>> r.square = 10 >>> r.getArea() 100 >>> r.__dict__ {'width': 10, 'height': 10, 'squre': 10}
>>> class Rectangle: ... def __init__(self, width = 0, height = 0): ... self.width = width ... self.height = height ... def __setattr__(self, name, value): ... if name == 'square': ... self.width = value ... self.height = value ... else: ... self.__dict__[name] = value ... def getArea(self): ... return self.width * self.height ... >>> r = Rectangle() >>> r = Rectangle(4,5) >>> r.getArea() 20