__ getattr __
当你请求获取一个并没有定义的属性时,python将会调用此方法。下图示例当中,Count没有__ getattr __方法,我们获取obj1.mymin和obj2.mymax这两个参数都可以成功获取,但是当我们尝试得到obj1.mycurrent参数时,python抛出了属性异常AttributeError: 'Count' object has no attribute 'mycurrent'’
class Count():
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent) --> AttributeError: 'Count' object has no attribute 'mycurrent'
我们给Count类加上__ getattr __方法
class Count:
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
def __getattr__(self, item):
self.__dict__[item]=0
return 0
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent1)
虽然obj1.mycurrent1属性并没有定义,__ getattr __方法返回的值仍然被打印出来,
1
10
0
__ getattribute __
如果在你的类当中,存在__ getattribute __方法,Python将会为每个属性调用这个方法无论它存在与否。那我们使用 __ getattribute __ 方法的目的是?主要还是为了控制属性的访问,并且增加它们的安全性。如下图所示,任何人只要访问我以cur开头的属性,将抛出定义的异常。
class Count:
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
self.current=None
def __getattribute__(self, item):
if item.startswith('cur'):
raise AttributeError
return object.__getattribute__(self,item)
# or you can use ---return super().__getattribute__(item)
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)
控制台输出:
1
Traceback (most recent call last):
10
File "/Users/stellaye/PycharmProjects/getattrmethods/属性方法对比.py", line 17, in <module>
print(obj1.current)
File "/Users/stellaye/PycharmProjects/getattrmethods/属性方法对比.py", line 10, in __getattribute__
raise AttributeError
AttributeError
注意:
为了防止在__ getattribute __ 方法里的无限循环,它应该执行基础类的 __ getattribute __方法(同时传递要获得的属性).例如object. __ getattribute __(self, name) 或者 super(). __ getattribute __(item) 而不是 self. __ dict __[item]
总结
当你的类里面同时有 __ getattr __和 __ getattribute __ 这两个魔法方法时, __ getattribute __方法将会首先被调用.但是如果 __ getattribute __方法引发了AttributeError异常,那么这个异常会被忽略,取而代之 __ getattr __方法被调用。
class Count(object):
def __init__(self,mymin,mymax):
self.mymin=mymin
self.mymax=mymax
self.current=None
def __getattr__(self, item):
self.__dict__[item]=0
return 0
def __getattribute__(self, item):
if item.startswith('cur'):
raise AttributeError
return object.__getattribute__(self,item)
# or you can use ---return super().__getattribute__(item)
# note this class subclass object
obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)
输出
1
10
0