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

2024-04-17

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

import mat
class Klass(object):

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

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

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

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要创建每个方法,您需要将其绑定到当前本地范围。该范围有一个名为的变量实例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"

Here, make_attr创建一个新的作用域,因此该变量有唯一的实例value,每个创建的 lambda 对应一个。

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

lambda self, val=method_value: val 

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

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

最后,马蒂指出不同的答案 https://stackoverflow.com/a/33135707/925478如何修改我的make_attr应用所需装饰器的函数:

def make_attr(value):
    return mat.sell(mat.CanSet)(lambda self: value))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python setattr 用于带有装饰器的动态方法创建器 的相关文章

随机推荐