【问题标题】:Why can instance methods be called as class methods in Python 3?为什么在 Python 3 中可以将实例方法称为类方法?
【发布时间】:2018-06-14 16:37:22
【问题描述】:

考虑以下类:

class Foo(object):
    def bar(self):
        print(self)

在 Python 2 (2.7.13) 中,将 bar() 作为类方法调用会引发异常:

>>> Foo.bar('hello')
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 str instance instead)

>>> Foo.bar()
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)

bar() 作为实例方法被调用时,它会在不带参数的情况下将self 识别为实例

>>> Foo().bar('hello')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes exactly 1 argument (2 given)

>>> Foo().bar()
<__main__.Foo object at 0x10a8e1a10>

在 Python 3 (3.6.0) 中,当调用bar() 作为类方法时,第一个参数被接受为self

>>> Foo.bar('hello')
hello

>>> Foo.bar()
 Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() missing 1 required positional argument: 'self'

调用 bar() 作为实例方法的工作方式与 Python 2 中一样

>>> Foo().bar('hello')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes 1 positional argument but 2 were given

>>> Foo().bar()
<__main__.Foo object at 0x104ab34a8>

【问题讨论】:

  • 好问题。似乎他们删除了检查 python 3。为什么?也许是因为“最好请求宽恕而不是允许”。如果它有效,对你有好处,否则,你会在之后的某个时候遇到异常。
  • 我非常有信心,一个熟练而坚定的骗子猎人可以找到这个问题的骗子,因为我很确定我以前见过它......
  • 相关:stackoverflow.com/questions/3589311/… 但我不会称之为重复。

标签: python python-3.x oop


【解决方案1】:

在 Python 3 上,Foo.bar 就是您编写的 bar 函数。它接受一个名为self 的参数并打印它。你可以在任何东西上调用该函数,它会打印你传递给它的任何参数。

在 Python 2 上,Foo.bar 并不完全是您编写的 bar 函数。当您访问Foo.bar 时,Python 会生成一个包装bar 函数的未绑定方法对象。未绑定方法对象的工作方式与bar 函数很相似,主要区别在于验证它的第一个参数是Foo 的实例。你可以这样做

Foo.bar(some_foo_instance)

这将像some_foo_instance.bar() 一样工作,但调用Foo 的实现,绕过子类中的任何覆盖。不过你不能Foo.bar('hello')

Python 3 removed unbound method objects. 他们已经不存在了。这使语言更简单一些,但它删除了用于执行的验证未绑定方法对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-09
    • 1970-01-01
    • 2016-06-11
    • 1970-01-01
    • 1970-01-01
    • 2018-11-30
    相关资源
    最近更新 更多