@songying
2018-07-12T16:07:03.000000Z
字数 1789
阅读 1072
python特殊方法
__getattr__
__getattr__(self, name)
当用户试图访问一个根本不存在(或者暂时不存在)的属性时,你可以通过这个魔法方法来定义类的行为。
这个可以用于捕捉错误的拼写并且给出指引,使用废弃属性时给出警告(如果你愿意,仍然可以计算并且返回该属性),以及灵活地处理AttributeError。
只有当试图访问不存在的属性时它才会被调用,所以这不能算是一个真正的封装的办法。
__setattr__
和 __getattr__
不同, __setattr__
可以用于真正意义上的封装。它允许你自定义某个属性的赋值行为,不管这个属性存在与否,也就是说你可以对任意属性的任何变化都定义自己的规则。然后,一定要小心使用 __setattr__
,这个列表最后的例子中会有所展示。
__delattr__
这个魔法方法和 __setattr__
几乎相同,只不过它是用于处理删除属性时的行为。和 __setattr__
一样,使用它时也需要多加小心,防止产生无限递归(在__delattr__
的实现中调用 del self.name 会导致无限递归)。
__getattribute__
__getattribute__
看起来和上面那些方法很合得来,但是最好不要使用它。 __getattribute__
只能用于新式类。在最新版的Python中所有的类都是新式类,在老版Python中你可以通过继承 object 来创建新式类。 __getattribute__
允许你自定义属性被访问时的行为,它也同样可能遇到无限递归问题(通过调用基类的 __getattribute__`` 来避免)。
getattribute基本上可以替代
getattr` 。只有当它被实现,并且显式地被调用,或者产生 AttributeError 时它才被使用。 这个魔法方法可以被使用(毕竟,选择权在你自己),我不推荐你使用它,因为它的使用范围相对有限(通常我们想要在赋值时进行特殊操作,而不是取值时),而且实现这个方法很容易出现Bug。
__dir__(self)
定义对类的实例调用 dir() 时的行为,这个方法应该向调用者返回一个属性列表。一般来说,没必要自己实现 __dir__
。但是如果你重定义了 __getattr__
或者 __getattribute__
,乃至使用动态生成的属性,以实现类的交互式使用,那么这个魔法方法是必不可少的。
def __setattr__(self, name. value):
self.name = value
# 因为每次属性幅值都要调用 __setattr__(),所以这里的实现会导致递归
# 这里的调用实际上是 self.__setattr('name', value)。因为这个方法一直
# 在调用自己,因此递归将持续进行,直到程序崩溃
def __setattr__(self, name, value):
self.__dict__[name] = value # 使用 __dict__ 进行赋值
# 定义自定义行为
class AccessCounter(object):
''' 一个包含了一个值并且实现了访问计数器的类
每次值的变化都会导致计数器自增'''
def __init__(self, val):
super(AccessCounter, self).__setattr__('counter', 0)
super(AccessCounter, self).__setattr__('value', val)
def __setattr__(self, name, value):
if name == 'value':
super(AccessCounter, self).__setattr_('counter', self.counter + 1)
# 使计数器自增变成不可避免
# 如果你想阻止其他属性的赋值行为
# 产生 AttributeError(name) 就可以了
super(AccessCounter, self).__setattr__(name, value)
def __delattr__(self, name):
if name == 'value':
super(AccessCounter, self).__setattr('counter', self.counter + 1)
super(AccessCounter, self).__delattr(name)