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

 

posted @ 2017-08-08 10:38  耳木东木2  阅读(297)  评论(0编辑  收藏  举报