Python setattr() 函数
描述
语法
setattr 函数对应函数 getatt(),用于设置属性值,该属性必须存在。
setattr 语法:
setattr(object, name, value)
参数
- object -- 对象。
- name -- 字符串,对象属性。
- value -- 属性值。
实例
无。
以下实例展示了 setattr 的使用方法:
class A(object):
bar = 1
a = A()
getattr(a, 'bar') # 获取属性 bar 值
setattr(a, 'bar', 5) # 设置属性 bar 值
a.bar
Out[2]: 5
__getattr__方法
拦截点号运算。当对未定义的属性名称和实例进行点号运算时,就会用属性名作为字符串调用这个方法。如果继承树可以找到该属性,则不调用此方法
- class empty:
- def__getattr__(self, attrname):
- ifattrname =="age":
- return40
- else:
- raiseAttributeError, attrname
- x =empty()
- print(x.age) #40
- print(x.name) #error text omitted.....AttributeError, name
这里empty类和实例x并没有属性age,所以执行x.age时,就会调用__getattr__方法,对于name也是同样。
__setattr__方法
会拦截所有属性的的赋值语句。如果定义了这个方法,self.arrt = value 就会变成self,__setattr__("attr", value).这个需要注意。当在__setattr__方法内对属性进行赋值是,不可使用self.attr = value,因为他会再次调用self,__setattr__("attr", value),则会形成无穷递归循环,最后导致堆栈溢出异常。应该通过对属性字典做索引运算来赋值任何实例属性,也就是使用self.__dict__['name'] = value.
实现属性的私有化
- class PrivateExc(Exception):
- pass
- class Privacy:
- def__setattr__(self, attrname, value):
- ifattrname inself.privates:
- raisePrivateExc(attrname, self)
- else:
- self.__dict__[attrname]= value
- classTest1(Privacy):
- privates= ["age"]
- classTest2(Privacy):
- privates= ["name","age"]
- def__init__(self):
- self.__dict__["name"]= "sun"
- x =Test1()
- y =Test2()
- x.name = "Tom" #执行成功
- x.age =20 #执行失败,产生异常,该属性在privates列表内
- y.name = "Mike" #执行失败,产生异常,该属性在privates列表内
- y.age =20 #执行成功
上述方式是python实现属性私有化的首选方式。
我们还可以通过重载 __getattr__ 和 __setattr__ 来拦截对成员的访问,需要注意的是 __getattr__ 只有在访问不存在的成员时才会被调用。
>>> class Class1:
def __getattr__(self, name):
print "__getattr__"
return None
def __setattr__(self, name, value):
print "__setattr__"
self.__dict__[name] = value
>>> a = Class1()
>>> a.x
__getattr__
>>> a.x = 123
__setattr__
>>> a.x
123
如果类型继承自 object,我们可以使用 __getattribute__ 来拦截所有(包括不存在的成员)的获取操作。
注意在 __getattribute__ 中不要使用 "return self.__dict__[name]" 来返回结果,因为在访问 "self.__dict__" 时同样会被 __getattribute__ 拦截,从而造成无限递归形成死循环。
>>> class Class1(object):
def __getattribute__(self, name):
print "__getattribute__"
return object.__getattribute__(self, name)
>>> a = Class1()
>>> a.x
__getattribute__
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
a.x
File "<pyshell#1>", line 4, in __getattribute__
return object.__getattribute__(self, name)
AttributeError: 'Class1' object has no attribute 'x'
>>> a.x = 123
>>> a.x
__getattribute__
123