我定义了以下装饰器:
class My_Decorator:
def __init__(self, marker_list):
assert isinstance(marker_list, list)
self.marker_list = marker_list
def __call__(self, original_class):
for this_marker in self.marker_list:
def _method(self):
print("marker on this func attribute: ", _method.marker)
_method.marker = this_marker
setattr(
original_class,
this_marker,
_method
)
return original_class
@My_Decorator(['marker1', 'marker2'])
class A: pass
我期望可调用方法内部的循环将生成不同的_method
个对象,并相应地分配,每次迭代都有自己对应的_method.marker
。但是,下面是我得到的:
a = A()
>>> A.marker1
<function My_Decorator.__call__.<locals>._method at 0x7fc0ded21bf8>
>>> A.marker2
<function My_Decorator.__call__.<locals>._method at 0x7fc0dec371e0>
>>> A.marker1.marker
'marker1'
>>> A.marker2.marker
'marker2'
>>> a.marker1()
marker on this func attribute: marker2
>>> a.marker2()
marker on this func attribute: marker2
正如我们在这里可以看到的那样,该方法停留在循环的最后一个标记处。 有人可以帮忙指出原因吗?感谢。
答案 0 :(得分:0)
在循环内定义一个函数会导致后期绑定:事实上你在循环外调用函数,使它查找最新的_method
定义。
实施早期绑定将解决您的问题:
def __call__(self, original_class):
for this_marker in self.marker_list:
# set a default value, which is the currently iterated "this_marker"
def _method(self, this_marker=this_marker):
# move the attribute setting for "_method" inside the function
_method.marker = this_marker
print("marker on this func attribute: ", _method.marker)
setattr(
original_class,
this_marker,
_method
)
return original_class
现在:
>>> a.marker1()
marker on this func attribute: marker1
>>> a.marker2()
marker on this func attribute: marker2