为什么在Python 3中可以将实例方法作为类方法调用?

vii*_*iis 3 python oop python-3.x

考虑以下课程:

class Foo(object):
    def bar(self):
        print(self)
Run Code Online (Sandbox Code Playgroud)

在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)
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

在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'
Run Code Online (Sandbox Code Playgroud)

调用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>
Run Code Online (Sandbox Code Playgroud)

use*_*ica 9

在Python 3上,Foo.bar只是bar你写的那个函数.它需要一个参数,恰好命名self并打印出来.你可以在任何东西上调用该函数,它会打印你传递的任何参数.

在Python 2上,Foo.bar并不是bar你写的功能.当您访问时Foo.bar,Python会生成一个包装该函数的未绑定方法对象bar.未绑定的方法对象的工作方式大多与bar函数类似,主要区别在于验证其第一个参数是实例Foo.你可以做到

Foo.bar(some_foo_instance)
Run Code Online (Sandbox Code Playgroud)

哪个会工作some_foo_instance.bar(),但调用Foo的实现,绕过子类中的任何覆盖.但是你做不到Foo.bar('hello').

Python 3删除了未绑定的方法对象.它们不再存在.这使得语言更简单,但它删除了用于执行的验证未绑定方法对象.