gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-30 01:04:01 27 4
gpt4 key购买 nike

这个有效:

>>> 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 属性成为第一个参数(通常命名为 self) 到底层函数对象,绑定(bind)方法的 im_func 属性。要覆盖它,您显然需要重新绑定(bind) im_self(编辑:或改为调用 im_func)——无论您在参数方面做什么当然,通过不会对其产生任何影响。是的,这是绑定(bind)方法对象在 Python 中工作的记录方式(不仅仅是实现细节:每个正确的 Python 实现都必须完全按照这种方式进行)。因此,从某种意义上说,它是“必要的”,因为它是使 Python 成为真正语言的一部分,而不是成为一种略有不同或截然不同的语言。当然,您可以设计一种不同的语言,选择按照完全不同的规则进行游戏,但是——当然不会是 Python。

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

TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)

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

这个晦涩的角落案例当然可以通过使未绑定(bind)的方法变得更加复杂来改变(使用 Python 3.2 补丁,如果以及何时语言更改“卡住”结束;-):他们必须反省并保存第一个-创建时参数的名称,并在每次调用时检查关键字参数,以防有人按名称而不是按位置传递 self。我不认为这会破坏任何现有的工作代码,它只会减慢几乎所有现有的 Python 程序。如果您编写并提出了一个实现此复杂功能的补丁,并在 python-dev 上积极倡导它以对抗必然会到来的反对 Storm ,那么毫无疑问,您有 > 0 的机会来插入它通过——祝你好运.

与此同时,我们其他人将继续获取 im_func 属性,作为一个荒谬的微小额外步骤,这是一个非常复杂的元编程大厦,以保证这样的改变 - - 这根本不是一个“特例”,与将命名参数传递给不采用命名参数(并且不'公开他们的“参数名称”以轻松允许将命名参数转换为位置参数(现在 将是一个值得攻击的风车,恕我直言:在所有可调用对象中,内置函数是元编程最糟糕的,因为那个!-)。

关于python - 为什么我不能将 self 作为命名参数传递给 Python 中的实例方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2443673/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com