unbound method __init__() error with python2 but not with python3

huangapple go评论95阅读模式
英文:

unbound method __init__() error with python2 but not with python3

问题

这与我之前的问题有关:https://stackoverflow.com/questions/76324839/unbound-method-init-error-in-unit-tests-but-not-in-regular-executions?noredirect=1#comment134593579_76324839

我创建了一个下面的最小可重现示例:

class Base:
  def __init__(self):
    print("base constructor")

class derived(Base):
  def __init__(self):
    print("derived constructor")

class Secondary(Base):
  def __init__(self):
    derived.__init__(self)

s = Secondary()

如果你使用 python3.7(或任何 Python3 版本,我认为都可以),它可以正常运行,但是在 python2.7 中,你会遇到错误:

$ python2.7 test.py
Traceback (most recent call last):
  File "test.py", line 13, in <module>
    s = Secondary()
  File "test.py", line 11, in __init__
    derived.__init__(self)
TypeError: unbound method __init__() must be called with derived instance as first argument (got Secondary instance instead)

为什么这在 Python3 中可以正常工作,但在 Python2 中不行?是否有办法让这在 Python2 中工作?

我也尝试使用 super(必须让 Base 继承 object 才能使用它):

class Base(object):
  def __init__(self):
    print("base constructor")

class derived(Base):
  def __init__(self):
    print("derived constructor")

class Secondary(Base):
  def __init__(self):
    super(derived, self).__init__()

s = Secondary()

在 Python2 中仍然存在问题。错误消息变了(我认为意思类似):

$ python2.7 test.py
Traceback (most recent call last):
  File "test.py", line 13, in <module>
    s = Secondary()
  File "test.py", line 11, in __init__
    super(derived, self).__init__()
TypeError: super(type, obj): obj must be an instance or subtype of type
英文:

This is related to my earlier question: https://stackoverflow.com/questions/76324839/unbound-method-init-error-in-unit-tests-but-not-in-regular-executions?noredirect=1#comment134593579_76324839

I made a minimal reproducible example below:

class Base:
  def __init__(self):
    print(&quot;base constructor&quot;)

class derived(Base):
  def __init__(self):
    print(&quot;derived constructor&quot;)

class Secondary(Base):
  def __init__(self):
    derived.__init__(self)

s = Secondary()

If you run this with python3.7 (or any python3 version I think), it works fine, but with python2.7, you get the error

$ python2.7 test.py
Traceback (most recent call last):
  File &quot;test.py&quot;, line 13, in &lt;module&gt;
    s = Secondary()
  File &quot;test.py&quot;, line 11, in __init__
    derived.__init__(self)
TypeError: unbound method __init__() must be called with derived instance as first argument (got Secondary instance instead)

Why does this work with python3 but not python2? Is there a way to make this work with python2?

Also tried using super (had to make Base inherit object to use it):

class Base(object):
  def __init__(self):
    print(&quot;base constructor&quot;)

class derived(Base):
  def __init__(self):
    print(&quot;derived constructor&quot;)

class Secondary(Base):
  def __init__(self):
    super(derived, self).__init__()

s = Secondary()

There's still an issue with python2. The error changes (similar meaning I think):

$ python2.7 test.py
Traceback (most recent call last):
  File &quot;test.py&quot;, line 13, in &lt;module&gt;
    s = Secondary()
  File &quot;test.py&quot;, line 11, in __init__
    super(derived, self).__init__()
TypeError: super(type, obj): obj must be an instance or subtype of type

答案1

得分: 2

在Python 2中,访问一个function类型的类属性始终会产生一个instancemethod实例,无论您是通过类还是类的实例来访问它。

>>> class Foo(object):
...   def __init__(self):
...     pass
...
>>> type(Foo.__init__)
<type 'instancemethod'>
>>> type(Foo().__init__)
<type 'instancemethod'>

唯一的区别在于当您调用instancemethod时,它是否具有可以传递给函数的对象引用。

>>> f = Foo()
>>> Foo.__init__()  # 错误
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method __init__() must be called with Foo instance as first argument (got nothing instead)
>>> Foo.__init__(f)  # 正确
>>> f.__init__()  # 正确

在Python 3中,访问类上的function类型的类属性会产生原始函数;只有当您通过类的实例访问它时,才会得到一个method实例。

>>> class Foo:
...   def __init__(self):
...     pass
...
>>> type(Foo.__init__)
<class 'function'>
>>> type(Foo().__init__)
<class 'method'>
英文:

In Python 2, accessing a function-valued class attribute always produces an instance of instancemethod, whether you access it via the class or an instance of the class.

&gt;&gt;&gt; class Foo(object):
...   def __init__(self):
...     pass
...
&gt;&gt;&gt; type(Foo.__init__)
&lt;type &#39;instancemethod&#39;&gt;
&gt;&gt;&gt; type(Foo().__init__)
&lt;type &#39;instancemethod&#39;&gt;

The only difference is whether the instancemethod has a reference to an object that can be passed to the function when you call the instancemethod.

&gt;&gt;&gt; f = Foo()
&gt;&gt;&gt; Foo.__init__()
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
TypeError: unbound method __init__() must be called with Foo instance as first argument (got nothing instead)
&gt;&gt;&gt; Foo.__init__(f)  # OK
&gt;&gt;&gt; f.__init__()  # OK

In Python 3, accessing a function-valued class attribute on a class produces the raw function; only when you access it via an instance of the class do you get an instance of method.

&gt;&gt;&gt; class Foo:
...   def __init__(self):
...     pass
...
&gt;&gt;&gt; type(Foo.__init__)
&lt;class &#39;function&#39;&gt;
&gt;&gt;&gt; type(Foo().__init__)
&lt;class &#39;method&#39;&gt;

huangapple
  • 本文由 发表于 2023年5月25日 01:32:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76326080.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定