本文讲的是带你声明 Python 中的动态属性,
以下实例均为 Python 3.5 版本,但同样适用于 Python 2.x 和 Python 3.x 版本。
重写类中的 __getattr__
魔术方法是 Python 中实现动态属性的很普通的方法。试想有这样一个数据词典 AttrDict
,它允许类似属性的方式访问其存储的键值对:
class AttrDict(dict):
def __getattr__(self, item):
return self[item]
这个简化的 AttrDict
类允许以类似属性的方式获取数据字典的值,同时,它允许一种非常简单的方式来设置键值对的值。无论哪种情况下,它都可以这样做:
>>> attrd = AttrDict()
... attrd["key"] = "value"
... print(attrd.key)
value
重写 __getattr__
方法(和 __setattr__
动态属性在交互的 shell 下有两大使用问题。第一个问题就是当用户使用 dir
>>> dir(attrd) # 我想知道如何使用 attrd
['__class__', '__contains__', ... 'keys', 'values']
>>> # 没有动态属性 [傲娇脸]
第二个问题是自动完成——如果我们照常设置 normal_attribute
属性,大部分主流的 shell 环境 1 下都能自动完成。
dynamic_attribute
__dir__
,这样不但能提高用户体验还能一石二鸟地解决以上两个问题。如果对象内有名为 __dir__()的方法,方法被调用时必须返回属性列表。这使得对象可以实现一个自定义的__getattr__() 或者 __getattribute__() 方法,来自定义 dir()
实现 __dir__
class AttrDict(dict):
def __getattr__(self, item):
return self[item]
def __dir__(self):
return super().__dir__() + [str(k) for k in self.keys()]
这样 dir(attrd)
将会返回动态属性和普通属性。有趣的是,shell 环境将会使用 __dir__
!因此我们毫不费力就实现了自动完成 2功能: