这有效:
>>> 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
但是,为什么这在Python 2.x中不起作用?
>>> 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的语义是某种必要还是只是实现的产物。
最佳答案
z.bar
是一个绑定(bind)方法-它已经具有im_self
属性,该属性成为基础函数对象(绑定(bind)方法的self
属性)的第一个参数(通常称为im_func
)。要覆盖它,显然您需要重新绑定(bind)im_self
(编辑:或调用im_func
)–无论如何,关于参数传递的操作都不会对其产生任何影响。是的,那是和所记录的方法绑定(bind)方法对象在Python中的工作方式(不仅仅是实现细节:每个正确的Python实现都必须以这种方式来完成)。因此,从某种意义上说,这是使Python成为真正的语言的一部分,而不是稍微或完全不同的语言,这是“必要的”。当然,您可以设计一种不同的语言,以完全不同的规则进行选择,但是-当然,它不是Python。
编辑:OP的编辑澄清了他正在调用一个未绑定(bind)的方法,而不是绑定(bind)的方法。这仍然不起作用,并且从错误消息中可以清楚地看出尝试的原因:
该非常清晰的错误消息所基于的规则是,实例必须是第一个参数 (因此,位置当然是:命名参数没有顺序)。 unbound方法不会“知道”(也不在乎)该参数的名称是什么(并且使用self
作为名称只是一种约定,并不是(Python语言的规则)):它只关心明确的名称“第一个论点”的条件(当然还有位置论点)。
通过使未绑定(bind)的方法变得更加复杂,可以肯定地改变这种晦涩的特殊情况(使用Python 3.2补丁,如果并且当语言更改的“卡住”结束时;-):他们必须自省(introspection)并保存第一个参数的名称。在创建时,请检查每个调用的关键字参数,以防有人按名称而不是按位置传递self
。我认为这不会破坏任何现有的有效代码,只会减慢每个现有的Python程序的速度。如果您编写并提出实现此复杂性的补丁程序,并积极使用python-dev来提倡其抵制肯定会出现的反对派 Storm ,那么毫无疑问,您有> 0的机会克服它-祝您好运。
同时,我们其余的人将继续获得im_func
属性,这是在必须非常复杂的元编程独立大厦中进行的一个荒谬的额外步骤,以保证进行此更改-这不是“特殊情况”与将命名参数传递给不带命名参数的内置的适应性艰巨(并且不公开其“参数名称”以轻松地将命名参数转换为位置参数(现在,恕我直言,这将是一个值得攻击的风车:在所有可调用函数中,内置函数是元程序最糟糕的,因此!-)。
关于python - 为什么我不能将self作为命名参数传递给Python中的实例方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2443673/