目标是创建一个模拟类,其行为类似于db resultset。
例如,如果数据库查询使用dict表达式{'ab':100, 'cd':200}
返回,那么我希望看到:
>>> dummy.ab
100
起初我想也许我可以这样做:
ks = ['ab', 'cd']
vs = [12, 34]
class C(dict):
def __init__(self, ks, vs):
for i, k in enumerate(ks):
self[k] = vs[i]
setattr(self, k, property(lambda x: vs[i], self.fn_readyonly))
def fn_readonly(self, v)
raise "It is ready only"
if __name__ == "__main__":
c = C(ks, vs)
print c.ab
但是c.ab
返回一个属性对象。
用k = property(lambda x: vs[i])
替换setattr
行完全没有用。
那么,在运行时创建实例属性的正确方法是什么?
p.S.我知道在How is the ^{
所以你想要的是一本字典,你可以把a['b']拼成a.b?
很简单:
我想我应该扩大这个答案,因为我年纪大了,更聪明了,知道发生了什么事。迟到总比不到好。
您可以动态地将属性添加到类中。但这就是问题所在:必须将其添加到类中。
一个
property
实际上是一个叫做descriptor的东西的简单实现。它是一个对象,在给定的类上为给定的属性提供自定义处理。有点像把一棵巨大的if
树从__getattribute__
中分离出来的方法。当我在上面的示例中要求
foo.b
时,Python看到类上定义的b
实现了描述符协议-这意味着它是一个具有__get__
、__set__
或__delete__
方法的对象。描述符声明负责处理该属性,因此Python调用Foo.b.__get__(foo, Foo)
,返回值作为属性的值传回给您。在property
的情况下,这些方法中的每一个只调用传递给property
构造函数的fget
、fset
或fdel
。描述符实际上是Python公开其整个OO实现管道的方式。实际上,还有一种类型的描述符比
property
更常见。简陋的方法只是另一种描述。它的
__get__
将调用实例作为第一个参数;实际上,它这样做:无论如何,我怀疑这就是为什么描述符只对类起作用的原因:它们首先是为类提供动力的东西的形式化。它们甚至是规则的例外:显然可以将描述符分配给类,类本身就是
type
的实例!事实上,尝试读取Foo.b
仍然调用property.__get__
;描述符在作为类属性访问时返回它们自己只是一种习惯。我认为几乎所有Python的OO系统都可以用Python来表示是很酷的。:)
哦,如果你感兴趣的话,我刚才写了一篇wordy blog post about descriptors。
似乎您可以用^{} 更简单地解决这个问题,因为您提前知道了整个字段列表。
如果您确实需要编写自己的setter,则必须在类级别执行元编程;
property()
不能在实例上工作。相关问题 更多 >
编程相关推荐