MetaPython:向类添加方法

MetaPython:向类添加方法,python,binding,metaprogramming,Python,Binding,Metaprogramming,我想在运行时向类定义添加一些方法。然而,当运行下面的代码时,我得到了一些令人惊讶的结果 test.py 在命令行上进行测试时,我得到以下结果: >>> import test >>> k = test.klass() >>> k.f1() 2 >>> k.f2() 2 为什么k.f1()返回2而不是1?对我来说,这似乎有点违反直觉 笔记 这项测试是在kubuntu机器上使用python3.0完成的。我猜这是因为print(

我想在运行时向类定义添加一些方法。然而,当运行下面的代码时,我得到了一些令人惊讶的结果

test.py 在命令行上进行测试时,我得到以下结果:

>>> import test
>>> k = test.klass()
>>> k.f1()
2
>>> k.f2()
2
为什么
k.f1()
返回2而不是1?对我来说,这似乎有点违反直觉

笔记
这项测试是在kubuntu机器上使用python3.0完成的。

我猜这是因为
print(i)
打印
i
不是通过值,而是通过引用。因此,当离开for循环时,i具有值2,这两次都将被打印

我猜这是因为
print(i)
print
i
不是通过值,而是通过引用。因此,当离开for循环时,i具有值2,这两次都将被打印

这是绑定的常见问题——您希望在函数内部使用
i
进行早期绑定,而Python正在为其进行后期绑定。您可以通过以下方式强制较早的绑定:

class klass(object):
    pass

for i in [1,2]:
    def f(self, i=i):
        print(i)
    setattr(klass, 'f' + str(i), f)
或者将f包装到以i为参数的外部函数层中:

class klass(object):
    pass

def fmaker(i):
    def f(self):
        print(i)
    return f

for i in [1,2]:
    setattr(klass, 'f' + str(i), fmaker(i))

这是绑定的常见问题——您希望在函数内部使用
i
,而Python正在为其进行后期绑定。您可以通过以下方式强制较早的绑定:

class klass(object):
    pass

for i in [1,2]:
    def f(self, i=i):
        print(i)
    setattr(klass, 'f' + str(i), f)
或者将f包装到以i为参数的外部函数层中:

class klass(object):
    pass

def fmaker(i):
    def f(self):
        print(i)
    return f

for i in [1,2]:
    setattr(klass, 'f' + str(i), fmaker(i))

我认为,像我在回答中所做的那样,将重点放在早期绑定与后期绑定上,而不是“按值”与“按引用”上,会更清晰。我给出的两种解决方案仍然是通过引用(在Python中不能是其他方式;-),但它们解决问题的方法是通过两种方式中的任意一种来强制标识符的早期绑定。我认为更清楚的是,应该像我在回答中所做的那样,关注早期绑定与晚期绑定,而不是“按值”与“按引用”。我给出的两种解决方案仍然是通过引用(在Python中不能是其他方式;-),但它们解决问题的方式是通过两种方式中的任何一种强制更早地绑定标识符。很好的答案,这肯定解决了我的问题。有什么地方可以让我找到关于后期绑定和早期绑定的详细信息吗?这不是我以前研究过的问题。回答得好,我在面试的时候问了一些类似的问题。回答得好,这肯定解决了我的问题。有什么地方可以让我找到关于后期绑定和早期绑定的详细信息吗?这不是我以前研究过的问题。回答得好,我在面试的时候也问过类似的问题