为什么我不能将 self 作为命名参数传递给 Python 中的实例方法?

2023-11-25

这有效:

>>> 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 is a bound方法——它已经有一个im_self成为第一个参数的属性(通常命名为self) 到底层函数对象,绑定方法的im_func属性。要覆盖它,您显然需要重新绑定im_self (edit: 或致电im_func相反)——当然,无论你在参数传递方面做什么都不会对它产生任何影响。是的,那就是the记录了绑定方法对象在 Python 中的工作方式(不仅仅是实现细节:每个正确的 Python 实现都必须完全按照这种方式进行)。所以它是“必要的”,因为它是使 Python 成为真正的语言的一部分,而不是成为一种略有不同或强烈不同的语言。当然,您可以设计一种不同的语言,选择遵循完全不同的规则,但是——当然,它不会是 Python。

Edit:OP 的编辑澄清了他正在调用unbound方法,而不是绑定方法。这仍然不起作用,从尝试得到的错误消息中可以清楚地看出原因:

类型错误:未绑定方法 bar() 必须 首先以 Foo 实例调用 争论(什么也没得到)

这个非常明确的错误消息背后的规则是该实例必须是第一个参数(所以当然是位置参数:命名参数没有顺序)。未绑定方法不“知道”(也不关心)该参数是什么name可能是(并且使用名称self因为它只是一个习俗, notPython 语言的规则):它只关心“第一个参数”的明确条件(当然,在位置参数中)。

这个晦涩的极端情况肯定可以通过使未绑定的方法变得更加复杂来改变(使用Python 3.2补丁,如果并且当语言更改“冻结”结束时;-):他们必须内省并保存第一个参数的名称在创建时,并检查每次调用的关键字参数,以防万一有人通过self按名称而不是按职位。我不认为这会破坏任何现有的工作代码,它只会减慢几乎所有现有的 Python 程序的速度。如果你编写并提出一个实现这个复杂性的补丁,并在 python-dev 上积极倡导它,以对抗必然到来的反对风暴,那么毫无疑问你有 > 0 的机会来推动它——祝你好运。

与此同时,我们其他人将继续获得im_func相反,作为一个荒谬的微小额外步骤,必须是一个相当复杂的元编程大厦才能保证这样的改变——与适应命名的可怕困难相比,它根本不是一个“特殊情况”——参数传递给builtins那不take命名参数(并且不要公开它们的“参数名称”,以便轻松地将命名参数转换为位置参数(现在that将是一个值得攻击的风车,恕我直言:在所有可调用对象中,内置函数是最难进行元编程的,因此!-)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我不能将 self 作为命名参数传递给 Python 中的实例方法? 的相关文章