为什么我不能将self作为命名参数传递给Python中的实例方法? [英] Why can't I pass self as a named argument to an instance method in Python?

查看:271
本文介绍了为什么我不能将self作为命名参数传递给Python中的实例方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这有效:

>>> 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中不起作用?

But why doesn't this work in 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的语义是某种必要还是只是实现的产物.

This makes metaprogramming more difficult, because it requires special case handling. I'm curious if it's somehow necessary by Python's semantics or just an artifact of implementation.

推荐答案

z.bar bound 方法-它已经具有im_self属性,该属性成为第一个参数(通常命名为self)到基础函数对象,即绑定方法的im_func属性.要覆盖它,显然您需要重新绑定im_self(编辑:或调用im_func)-无论您在参数传递方面做什么都不会对其产生任何影响, 当然.是的,这是 记录的方法绑定方法对象在Python中的工作方式(不仅仅是实现细节:每个正确的Python实现都必须完全采用这种方式).因此,从某种意义上说,这是使Python成为真正的语言的一部分,而不是稍微或完全不同的语言,这是必要的".当然,您可以设计一种不同的语言,选择按照完全不同的规则播放,但是-当然,它不是Python.

z.bar is a bound method -- it already has an im_self attribute that becomes the first argument (conventionally named self) to the underlying function object, the bound method's im_func attribute. To override that you obviously need to re-bind im_self (edit: or call the im_func instead) -- whatever you do in terms of argument passing is not going to have any effect on it, of course. Yep, that's the documented way bound methods object work in Python (not just an implementation detail: every correct Python implementation has to do it exactly this way). So it's "necessary" in the sense that it's part of what makes Python exactly the language it is, as opposed to being a slighty or strongly different language. Of course you could design a different language that chooses to play by completely different rules, but -- it wouldn't be Python, of course.

编辑:OP的编辑澄清了他是在调用 unbound 方法,而不是绑定方法.这仍然不起作用,并且从尝试得到的错误消息中清楚了原因:

Edit: the OP's edits clarified he's calling an unbound method, not a bound one. This still doesn't work, and the reason is clear from the error message the attempt gets:

TypeError:未绑定方法bar()必须 首先被Foo实例调用 争论(什么也不要做)

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

此非常清楚的错误消息所依据的规则是,实例必须是第一个参数(因此当然是位置参数:命名参数没有顺序). unbound方法不会知道"(也不在乎)该参数的 name 可能是什么(并且使用名称self只是它是一个惯例不是 Python语言的规则):它只关心第一个参数"的明确条件(当然还有位置参数).

The rule underlying this very clear error message is that the instance must be the first argument (so of course a positional one: named arguments have no ordering). The unbound method doesn't "know" (nor care) what that parameter's name may be (and the use of name self for it is only a convention, not a rule of the Python language): it only care about the unambiguous condition of "first argument" (among the positional ones, of course).

通过使未绑定的方法变得更加复杂,可以肯定地改变这种晦涩的极端情况(使用Python 3.2补丁,如果并且当语言更改的冻结"结束时;-):他们必须进行内省并保存第一个方法. -argument在创建时的名称,并在每次调用时检查关键字参数,以防有人通过名称而不是位置传递self的情况.我认为这不会破坏任何现有的有效代码,只会减慢每个现有的Python程序的速度.如果您编写并提出实现此复杂性的补丁程序,并积极使用python-dev来倡导它,以抗击肯定要面对的反对派风暴,那么毫无疑问,您有> 0的机会克服它-祝您好运

This obscure corner case could certainly be altered (with a Python 3.2 patch, if and when the language-changes "freeze" ends;-) by making unbound methods seriously more complicated: they'd have to introspect and save the first-argument's name at creation time, and check keyword arguments on each call just in case somebody's passing self by name instead of by position. I don't think this would break any existing, working code, it would only slow down just about every existing Python program. If you write and propose a patch implementing this complication, and get active on python-dev to advocate for it against the sure-to-come firestorm of opposition, you do no doubt stand a > 0 chance to ram it through -- good luck.

我们其余的人将继续获取im_func属性,这是元数据编程的一个非常荒谬的额外步骤,可以保证进行这种更改,这是一个非常荒谬的额外步骤,但这不是完全是特殊情况",与将命名参数传递给内置插件而又不采用命名参数(并且不暴露其参数名称"以轻松地将命名参数转换为位置参数(现在将是值得攻击的风车,恕我直言:在所有可调用函数中,内建函数对于元程序而言是最糟糕的!- ).

The rest of us, meanwhile, will keep getting the im_func attribute instead, as one absurdly-tiny extra step in what has to be a pretty complicated inded edifice of metaprogramming to warrant such a change -- it isn't a "special case" at all, compared with the horrid difficulties of adapting named-argument passing to builtins that don't take named arguments (and don't expose their "argument names" to easily allow the transformation of named arguments into positional ones (now that would be a windmill worth attacking, IMHO: of all callables, builtins are the worst to metaprogram about, because of that!-).

这篇关于为什么我不能将self作为命名参数传递给Python中的实例方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆