getattr(self, item):
在访问对象的item属性的时候,如果对象并没有这个相应的属性,方法,那么将会调用这个方法来处理。。。这里要注意的时,假如一个对象叫obj, 他有一个属性:obj.name = "parker",那么在访问obj.name的时候因为当前对象有这个属性,那么将不会调用getattr()方法,而是直接返回了拥有的name属性了:代码如下
class Foo(object):
def __init__(self):
self.name = 'parker'
def __getattr__(self, item):
print('getattr') # 如果没有name属性,f.name将触发此方法
return
f = Foo()
print(f.name)
setattr(self, item, value):
当试图对象的item特性赋值的时候将会被调用。。
这里可能会有坑,稍微不小心就会陷入递归。用时需要注意,下面是用法:
class Foo(object):
def __init__(self):
self.name = 'parker'
def __getattr__(self, item):
print('getattr') # 如果没有name属性,f.name将触发此方法
return
def __setattr__(self, key, value):
self.__dict__[key] = value
self.key = value # 别这么写,报错
f = Foo()
f.age = 12
print(f.age)
它是会拦截所有属性的的赋值语句。如果定义了这个方法,self.arrt = value 就会变成self,setattr("attr", value).这个需要注意。当在setattr方法内对属性进行赋值是,不可使用self.attr = value,因为他会再次调用self,setattr("attr", value),则会形成无穷递归循环,最后导致堆栈溢出异常。应该通过对属性字典做索引运算来赋值任何实例属性,也就是使用self.dict['name'] = value.
getattribute(self, item):
这个只有在新式类中才有的,对于对象的所有特性的访问,都将会调用这个方法来处理,可以理解为在getattr之前
class Foo(object):
def __init__(self):
self.name = 'parker'
def __getattr__(self, item):
print('getattr') # 如果没有name属性,f.name将触发此方法
return
def __getattribute__(self, item):
print('getattribute')
return
# self.key = value # 别这么写,报错
f = Foo()
print(f.name) ###getattribute 执行了__getattribute__方法
扩展应用
可以通过重载setattr方法拦截对成员的访问,实现属性私有化
class Foo(object):
def __init__(self):
self.name = 'parker'
self.age = 18
def __setattr__(self, key, value):
pass
f = Foo()
print(f.age) #报错
print(f.__dict__) # {}访问不到
实现属性私有化的首选方式
class PrivateException(Exception):
pass
class Privacy:
privates = []
def __setattr__(self, key, value):
if key in self.privates:
raise PrivateException(key,self)
self.__dict__[key] = value
class Test1(Privacy):
privates = ['age']
class Test2(Privacy):
privates = ['name','age']
def __init__(self):
self.__dict__['name'] = 'sun'
t1 = Test1()
t2 = Test2()
t1.name = 'Parker'
t1.age = 12 #报错 该属性在privates内
t2.name = 'Tom'
t2.age = 12 #报错 该属性在privates内
网友评论