gpt4 book ai didi

带有装饰器的动态方法创建者的python setattr

转载 作者:行者123 更新时间:2023-11-28 19:48:25 25 4
gpt4 key购买 nike

我有一个定义了多个方法的类。

import mat
class Klass(object):

@mat.sell(mat.CanSet):
def method1(self):
return None

@mat.sell(mat.CanSet):
def method2(self):
return 'value2'

假设我有 10 个方法需要填充到这个“Klass”中。我想生成这些方法而不用显式地编写它们。所以我想做一个为每个方法做 setattr 的工厂。问题是我做了以下操作,最后一个方法具有最后一个值。每个都没有得到它的相关值,而是 value10。同样下面的解决方案没有实现装饰器,我不知道如何分配装饰器

class Klass(object):
pass

list1 = [('method1', 'value1'), ('method2', 'value2').....('method10', 'value10')]

for each in list1:
method_name, method_value = each
setattr(Klass, method_name, lambda self: method_value)

所以当我跟随....

k = Klass()
print k.method1(), method2()...., method10()

每种方法的结果都是 value10。不明白为什么 ?另外,任何人都可以帮助如何实现具有一个属性的装饰器吗?PS:如果您有不使用“setattr”的建议,我们也欢迎。

最佳答案

当您使用 lambda 创建每个方法时,您将它绑定(bind)到当前本地范围。该范围有一个名为 method_value 的变量实例,并且在每次循环后将其设置为一个新值。因为每个 lambda 都引用这个局部变量,所以它们都看到相同的值(例如,设置的最后一个值)。

如果您使用不同的方法创建 lambda,它将具有不同的作用域,因此您可以获得所需的行为:

class Klass(object):
pass

list1 = [('method1', 'value1'), ('method2', 'value2'), ('method10', 'value10')]

def make_attr(value):
return lambda self: value

for method_name, method_value in list1:
setattr(Klass, method_name, make_attr(method_value))

c = Klass()
print c.method1(), c.method2(), c.method10() # "value1, value2, value10"

在这里,make_attr 创建了一个新范围,因此变量 value 有唯一的实例,每个创建的 lambda 都有一个实例。

您还可以使用一个不错的技巧来创建一个 lambda 范围的内联变量,如下所示:

lambda self, val=method_value: val 

这里,val 被赋予 method_value 的值在 lambda 声明时,为每个 lambda 实例赋予它自己的值。这使您可以使用更紧凑的:

for method_name, method_value in list1:
setattr(Klass, method_name, lambda self, val=method_value:val))

最后,Marti 在 a different answer 中指出如何修改我的 make_attr 函数以应用所需的装饰器:

def make_attr(value):
return mat.sell(mat.CanSet)(lambda self: value))

关于带有装饰器的动态方法创建者的python setattr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33134609/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com