首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Python基础教程

9.5.3 __getattr__、 __setattr__等方法

可以拦截对对象属性的所有访问企图,其用途之一是在旧式类中实现特性(在旧式类中,函数property的行为可能不符合预期)。要在属性被访问时执行一段代码,必须使用一些魔法方法。

下面的四个魔法方法提供了你需要的所有功能(在旧式类中,只需使用后面三个)。

 __getattribute__(self, name):在属性被访问时自动调用(只适用于新式类)。

 __getattr__(self, name):在属性被访问而对象没有这样的属性时自动调用。

 __setattr__(self, name, value):试图给属性赋值时自动调用。

 __delattr__(self, name):试图删除属性时自动调用。

相比函数property,这些魔法方法使用起来要棘手些(从某种程度上说,效率也更低),但它们很有用,因为你可在这些方法中编写处理多个特性的代码。然而,在可能的情况下,还是使用函数property吧。

再来看前面的Rectangle示例,但这里使用的是魔法方法:

class Rectangle:

def __init__ (self):

self.width = 0

self.height = 0

def __setattr__(self, name, value):

if name == 'size':

self.width, self.height = value

else:

self. __dict__[name] = value

def __getattr__(self, name):

if name == 'size':

return self.width, self.height

else:

raise AttributeError()

如你所见,这个版本需要处理额外的管理细节。对于这个代码示例,需要注意如下两点。

 即便涉及的属性不是size,也将调用方法__setattr__。因此这个方法必须考虑如下两种情形:如果涉及的属性为size,就执行与以前一样的操作;否则就使用魔法属性__dict__。__dict__属性是一个字典,其中包含所有的实例属性。之所以使用它而不是执行常规属性赋值,是因为旨在避免再次调用__setattr__,进而导致无限循环。

 仅当没有找到指定的属性时,才会调用方法__getattr__。这意味着如果指定的名称不是size,这个方法将引发AttributeError异常。这在要让类能够正确地支持hasattr和getattr等内置函数时很重要。如果指定的名称为size,就使用前一个实现中的表达式。

注意 前面说过,编写方法__setattr__时需要避开无限循环陷阱,编写__getattribute__时亦如此。由于它拦截对所有属性的访问(在新式类中),因此将拦截对__dict__的访问!在 __getattribute__中访问当前实例的属性时,唯一安全的方式是使用超类的方法__getattribute__(使用super)。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181217G065H900?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券