【问题标题】:Python 2.7: Self works as positional but not as keyword argumentPython 2.7:Self 作为位置参数而不是关键字参数
【发布时间】:2016-09-29 02:20:49
【问题描述】:

这是一个最小的例子:

这适用于 python 3.5 和 2.7:

class A(object):
  def __init__(self, foo):
    self._foo = foo

class B(A):
  def __init__(self, foo):
    A.__init__(self, foo=foo)

b = B(1)

换行:

    A.__init__(self, foo=foo)

    A.__init__(self=self, foo=foo)

在 python 3.5 中运行没有问题,但在 python 2.7 中您将收到以下错误:

Traceback (most recent call last):
  File "self_key.py", line 9, in <module>
    b = B(1)
  File "self_key.py", line 7, in __init__
    A.__init__(self=self, foo=foo)
TypeError: unbound method __init__() must be called with A instance as first argument (got nothing instead)

在 python 2.7 中禁止 self 作为关键字参数还是一个错误?

更新

我知道 python 将使用绑定函数的第一个参数将引用传递给已调用的对象。我也知道__init__ 函数期望这个参数是类的一个实例。在这种情况下,A.__init__ 是未绑定的,因此我们必须手动提供该参数。

当我询问 self 作为关键字参数被禁止时,我说 self 作为“__init__ 的第一个参数”,它应该接收要初始化的对象的引用。变量本身的名称并不重要。我们完全可以把名字改成this:,例如:

class A(object):
  def __init__(this, foo):
    this._foo = foo

class B(A):
  def __init__(self, foo):
    A.__init__(this=self, foo=foo)

b = B(1)

它会是一样的。

我的问题是为什么在调用函数时,我们可以完美地将该参数指定为位置参数 (A.__init__(self, foo=foo)),但当我们尝试将其作为关键字参数 (A.__init__(this=self, foo=foo)) 传递时,python 2.7 会抛出错误。

【问题讨论】:

    标签: python-2.7 self keyword-argument


    【解决方案1】:

    实际上,您不必使用self 关键字,除非您保持一致。查看这个示例,我将 self 更改为 test

    class funcs():
        def init(test, a, b):
            test.a=a
            test.b=b
    
        def plus(test):
            c = test.a + test.b
            print"%d + %d = %d" %(test.a, test.b, c)
    
        def minus(test):
            c = test.a - test.b
            print"%d - %d = %d" %(test.a, test.b, c)
    
    obj = funcs()
    obj.init(10, 6)
    obj.plus()
    obj.minus()
    

    您可以尝试混合这些实例名称,这样就不会命名为self

    class A(object):
      def __init__(a_obj, foo):
        a_obj._foo = foo
    
    class B(A):
      def __init__(self, test, foo):
        A.__init__(self, a_obj=test, foo=foo) # here you pass object of class B and actually another object of class B
    
    a = A(2)
    b = B(a, 1)
    

    给出输出:

    A.__init__(self, a_obj=test, foo=foo) 
    TypeError: __init__() got multiple values for keyword argument 'a_obj'
    

    我不确定通过像这样传递这些对象实际上你想完成什么。在您的代码中,A 类中的 self 和 B 类中的 self 不是同一个对象。

    我想在这里:A.__init__(self=self, foo=foo) 你正在做类似A_instance=B_instance (self=self) 的事情

    【讨论】:

    • 我只是打电话给父母的__init__。我正在使用这种方法而不是使用super() 来控制多重继承中父级的__init__ 调用顺序,就像这样[stackoverflow.com/q/9575409/5705400]。所以 A 中的 self 和 B 中的 self 应该是同一个对象,因为我将 B 的引用传递给 A 的 __init__ 方法。这没关系,因为 B 继承自 A,所以它也是一个 A。
    【解决方案2】:

    始终使用self 作为实例方法的第一个参数。

    来源:Python Documentation

    【讨论】:

    • 通过阅读这篇文章,我觉得这适用于函数定义,而不是调用。
    猜你喜欢
    • 2018-12-12
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2016-11-30
    • 2013-01-13
    • 2017-05-21
    相关资源
    最近更新 更多