局部变量动态函数

2024-04-27 05:00:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图动态创建一组类属性,但是每个动态fget访问器都需要一个唯一的局部变量。在

下面是一个简化的例子:

class Test(object):
    def __metaclass__(name, bases, dict):
        for i in range(5):
            def fget(self, i=i):
                return i

            dict['f%d' % i] = property(fget)

        return type(name, bases, dict)

>>> t = Test()
>>> print t.f0, t.f1, t.f2, t.f4
0, 1, 2, 3, 4

为了使每个正确的'i'值可用于每个fget函数,我必须在创建函数时将其作为关键字参数传递。否则,所有函数都将看到相同的i实例(从range操作生成的最后一个实例)。在

对我来说这是一次糟糕的黑客攻击,有更好的方法吗?在


Tags: 实例函数nametestreturn属性def动态
3条回答

对于这个简化的例子,我认为您所拥有的功能非常好(除了有点老套)。虽然i=i部分可能很难看而且很棘手,但它是一种相对著名的闭包方法。如果你怕别人听不懂,就加一条评论。在

但是,如果你做的是更复杂的事情,我肯定会同意上面提到的s.Lott。在

另一种可能的方法是:

def make_property(i, dict):
    def fget(self):
        return i

    dict['f%d' % i] = property(fget)

class Test(object):
    def __metaclass__(name, bases, dict):
        for i in range(5):
            make_property(i, dict)

        return type(name, bases, dict)

就我个人而言,我觉得这使得整个过程更容易理解,因为你要把循环的每个迭代分离成它自己的函数。在

另一种方法是定义第二个函数,该函数将变量的值捕获为新的局部变量。E、 g.:

def make_prop_that_returns(i):
    return property(lambda self: i)

class Test(object):
    def __metaclass__(name, bases, dict):
        for i in range(5):
            dict['f%d' % i] = make_prop_that_returns(i)

        return type(name, bases, dict)

我不确定我是否会说这比你的方法干净得多,但这至少是一种选择。在

你能不能更清楚(不那么抽象)你想完成什么?定义动态fget可能不是最好的方法。在

“每个动态fget访问器都需要一个唯一的局部变量。”

这说明每个“属性”都是某个类的一个单独实例。在

考虑为此使用描述符,这样您就拥有了一个完整的类,而不是一些临时拼凑的实例变量。在

或者考虑在策略设计模式上使用一些变体,将这个“唯一的局部变量”委托给这个与属性相关的策略对象。在

相关问题 更多 >