python3--__getattr__和__setattr__捕捉属性的一个引用
__getattr__和__setattr__捕捉属性的一个引用
__getattr__方法是拦截属性点号运算。更确切地说,当通过对未定义(不存在)属性名称和实例进行点号运算时,就会用属性名称为字符串调用这个方祛。如果Python可通过其继承树搜索流程找到这个属性,该方法就不会被调用.因为有这种情况,__getattr__可以作为钩子来通过通用的方式响应属性请求。例子如下。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class empty:
def __getattr__(self, attrname):
if attrname == "age":
return 40
else:
raise ArithmeticError
x = empty()
print(x.age)
运行结果:
40
如果想使用这个方法,要确定是对属性字典做索引运算,来赋值任何实例的。使用self.__dict__['name'] = x,而不是self,name = x。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class accesscontrol:
def __setattr__(self, key, value):
if key == 'age':
self.__dict__[key] = value
else:
raise AttributeError
x = accesscontrol()
x.age = 40
print(x.age)
运行结果:
40
模拟实例属性的私有性
下列程序代码把上一个例子通用化了.让每个子类都有自己的私有变量名,这些变量名无法通过其实例进行赋值。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
class PrivateExc(Exception):pass
class Privacy:
def __setattr__(self, attrname, value):
if attrname in self.privates:
raise PrivateExc(attrname,self)
else:
self.__dict__[attrname] = value
class Test1(Privacy):
privates = ['age']
class Test2(Privacy):
privates = ['name', 'pay']
def __init__(self):
self.__dict__['name'] = 'Tom'
x = Test1()
y = Test2()
x.name = 'Bob'
print(x.name)
# y.name = 'Sue' # <== fails
# x.age = 40 # <== fails
y.age = 30
print(y.age)
运行结果:
Bob 30
浙公网安备 33010602011771号