python - 为什么具有相同 `id` 的两个函数可以具有不同的属性?

标签 python function dynamic methods types

为什么具有相同 id 值的两个函数可以具有不同的属性,例如 __doc____name__

这是一个玩具示例:

some_dict = {}
for i in range(2):
    def fun(self, *args):
        print i
    fun.__doc__ = "I am function {}".format(i)
    fun.__name__ = "function_{}".format(i)
    some_dict["function_{}".format(i)] = fun

my_type = type("my_type", (object,), some_dict)
m = my_type()

print id(m.function_0)
print id(m.function_1)
print m.function_0.__doc__
print m.function_1.__doc__
print m.function_0.__name__
print m.function_1.__name__
print m.function_0()
print m.function_1()

打印:

57386560
57386560
I am function 0
I am function 1
function_0
function_1
1 # <--- Why is it bound to the most recent value of that variable?
1

我已经尝试混合调用 copy.deepcopy(不确定函数是否需要递归副本或者它是否过分)但这不会改变任何东西。

最佳答案

您正在比较方法,每次您在实例或类上访问方法对象时(通过 descriptor protocol)都会重新创建方法对象。

一旦您测试了它们的 id(),您将再次丢弃该方法(没有对它的引用),因此当您创建另一个方法时,Python 可以自由地重用该 id。您想在这里测试实际功能,使用 m.function_0.__func__m.function_1.__func__:

>>> id(m.function_0.__func__)
4321897240
>>> id(m.function_1.__func__)
4321906032

方法对象从它们包装的函数中继承了 __doc____name__ 属性。实际的底层功能仍然是不同的对象。

至于返回1的两个函数;这两个函数都使用 i 作为闭包; i 的值是在您调用方法 时查找的,而不是在您创建函数时查找的。参见 Local variables in Python nested functions .

最简单的解决方法是添加另一个具有工厂函数的作用域:

some_dict = {}
for i in range(2):
    def create_fun(i):
        def fun(self, *args):
            print i
        fun.__doc__ = "I am function {}".format(i)
        fun.__name__ = "function_{}".format(i)
        return fun
    some_dict["function_{}".format(i)] = create_fun(i)

关于python - 为什么具有相同 `id` 的两个函数可以具有不同的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22566983/

相关文章:

python - 禁用 WTForms SelectField 中的选项之一

python - OpenCV:不规则形状区域中每种颜色的像素数?

python - 读取带有标题和数据的csv文件,并转换为xls文件

Javascript 提示变量返回 NaN

function - 如何从 Julia 结构的构造函数中调用函数?

java - 动态添加的微调器为空

javascript - 在 AngularJS 中使用动态元素

python - 使用 pandas.read_csv 分隔列

python - 在 Python 中查找函数的参数

javascript - 动态加载 jQuery 并在另一个函数中使用它