此作品:
>>> 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的语义是某种必要还是只是实现的产物。
Editz.bar
是bound方法-它已经具有im_self
属性,该属性成为基础函数对象(绑定方法的self
属性)的第一个参数(通常称为im_func
)。要覆盖它,显然您需要重新绑定im_self
(edit:或调用im_func
)–关于参数传递的任何操作当然都不会对其产生任何影响。是的,这是在Python中记录的方法绑定方法对象的工作方式(不仅仅是实现细节:每个正确的Python实现都必须完全采用这种方式)。因此,从某种意义上说,它是使Python成为真正的语言的一部分,而不是稍微或完全不同的语言,这是“必要的”。当然,您可以设计一种不同的语言,选择按照完全不同的规则播放,但是-当然,它不是Python。TypeError:未绑定方法bar()必须首先被Foo实例调用参数(什么也不要做)
此非常清晰的错误消息所依据的规则是,实例必须为
第一个参数(因此,位置必须是:命名参数没有顺序)。未绑定方法不会“知道”(也不在乎)该参数的name可能是什么(并且使用名称self
只是一个convention,not规则) Python语言的语言):它只关心“第一个参数”的明确条件(当然还有位置参数)。这种晦涩难解的情况肯定可以通过使未绑定方法变得更加复杂来改变(如果有,当语言更改“冻结”结束时,使用Python 3.2补丁;-):他们必须进行自我检查并保存第一个-参数在创建时的名称,并在每次调用时检查关键字参数,以防有人通过名称而不是位置传递self
。我认为这不会破坏任何现有的有效代码,只会减慢几乎每个现有的Python程序的速度。如果您编写并提出实现此复杂性的补丁程序,并积极使用python-dev来提倡其抵制肯定会遇到的反对派风暴,那么毫无疑问,您有机会> 0来克服它-祝您好运。
同时,我们其余的人将继续获得im_func
属性,这是元数据编程的一个非常荒谬的附加步骤,以保证进行这种更改,这是一个非常荒谬的额外步骤,这不是一个简单的步骤。与将命名参数传递给
builtins
而不使用take命名参数(并且不公开其“参数名称”以轻松允许将命名自变量转换为位置自变量(现在that将是一个值得攻击的风车,恕我直言:在所有可调用对象中,内置函数是元程序最糟糕的,因为那个!-])