这有效:
>>> def bar(x, y):
... print x, y
...
>>> bar(y=3, x=1)
1 3
这有效:
>>> class Foo(object):
... def bar(self, x, y):
... print x, y
...
>>> z = Foo()
>>> z.bar(y=3, x=1)
1 3
即便如此:
>>> Foo.bar(z, y=3, x=1)
1 3
但为什么这不起作用?
>>> Foo.bar(self=z, y=3, x=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)
这使得元编程更加困难,因为它需要特殊的案例处理。我很好奇Python的语义是否是必要的,或者仅仅是实现的工件。
答案 0 :(得分:6)
z.bar
是一个绑定方法 - 它已经有一个im_self
属性,它成为底层函数对象的第一个参数(通常命名为self
) ,绑定方法的im_func
属性。要覆盖它,你显然需要重新绑定im_self
(编辑:或者调用im_func
代替) - 无论你在参数传递方面做什么都不会有当然,对它有任何影响。是的, 记录的方法绑定方法对象在Python中工作(不仅仅是一个实现细节:每个正确的Python实现必须以这种方式完成)。所以它是“必要的”,因为它是使Python成为语言的一部分,而不是一种轻微或强烈不同的语言。当然,你可以设计一种不同的语言,选择完全不同的规则,但是 - 当然不是Python。
编辑:OP的编辑说明他正在调用未绑定的方法,而不是绑定方法。这仍然不起作用,原因从尝试获得的错误消息中可以清楚地看出:
TypeError:未绑定的方法bar()必须 首先用Foo实例调用 争论(没有取而代之)
这个非常明确的错误消息的基础规则是实例必须是第一个参数(所以当然是位置的:命名参数没有排序)。未绑定的方法不“知道”(也不关心)该参数的名称可能是什么(并且名称self
的使用只是约定 ,不是 Python语言的规则):它只关心“第一个参数”的明确条件(当然是位置的)。
这个模糊的角落案例当然可以改变(使用Python 3.2补丁,如果语言变化“冻结”结束;-)使非绑定方法更加复杂:他们必须反省并保存第一个-argument在创建时的名称,并在每个调用时检查关键字参数,以防有人通过名称而不是按位置传递self
。我认为这不会破坏任何现有的工作代码,它只会减慢每个现有的Python程序。如果你编写并提出一个实现这个复杂功能的补丁,并在python-dev上积极主张它反对肯定会遭到反对的风暴,你无疑会站在一个&gt;有机会通过它 - 祝你好运。
im_func
属性,这是一个非常微小的额外步骤,它必须是一个非常复杂的元编程大纲以保证这种变化 - 它不是完全是一个“特殊情况”,与将< - >> 命名参数的内置的命名参数调整的可怕困难相比较(并且不暴露他们的“论点名称”可以轻松地将命名参数转换为位置参数(现在 将是一个值得攻击的风车,恕我直言:在所有可调用的内容中,内置函数是元编程中最差的,因此! - 。)