我正在尝试在运行时为类设置新属性并附加lambda,其行为取决于某些特定于属性的数据。如果我在循环中设置属性,就像在B类中一样,第一个属性会被覆盖。按顺序设置它们是有效的。找不到问题。在其他问题中提到我应该使用__getattr__
而不是link中的属性。但我想了解这里的问题。
import time
class A():
def __init__(self, dynprops = ['a', 'b']):
setattr(A, 'a', property(lambda x: self.print_prop('a')))
setattr(A, 'b', property(lambda x: self.print_prop('b')))
def print_prop(self, dynprop):
print(time.time(), dynprop)
class B():
def __init__(self, dynprops = ['a', 'b']):
for prop in dynprops:
setattr(B, prop, property(lambda x: self.print_prop(prop)))
def print_prop(self, dynprop):
print(time.time(), dynprop)
a = A()
print(a.a)
print(a.b)
b = B()
print(b.a)
print(b.b)
给出
>> 1481137121.6755576 a
>> None
>> 1481137121.6756482 b
>> None
>> 1481137121.6757774 b
>> None
>> 1481137121.6758344 b
>> None
答案 0 :(得分:3)
这是因为prop
已更改为' b'然后保持这样。 lambda
函数返回prop
的当前值,而不是在lambda
创建期间分配给它的值。要避免这种行为,您应该使用闭包:
class B():
def __init__(self, dynprops = ['a', 'b']):
for prop in dynprops:
setattr(B, prop, property(self.printer(prop)))
def print_prop(self, dynprop):
print(time.time(), dynprop)
def printer(self, prop):
return lambda x: self.print_prop(prop)