当类中嵌入的函数是类的"方法"时?

Lon*_*ian 4 python

执行此操作时......

class A:
    def b(self, a):
        print a
    print dir(b)
print dir(A.b)
Run Code Online (Sandbox Code Playgroud)

它给出了结果:

['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__',
 '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__',
 '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure',
 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']

['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__get__',
 '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__',
 '__repr__', '__setattr__', '__str__', 'im_class', 'im_func', 'im_self']
Run Code Online (Sandbox Code Playgroud)

为什么这个不同?

adw*_*adw 7

Python 2中,第二种情况返回一个未绑定的方法,第一种情况是一个函数.从文档中,重点是我的:

用户定义的方法的对象可以被得到一个类的一个属性时创建(可能通过那个类的一个实例),如果该属性是一个用户定义的功能对象,未结合的用户定义的方法的对象,或一个类方法的对象.当属性是用户定义的方法对象时,仅当从中检索它的类与存储在原始方法对象中的类相同或派生类时,才会创建新的方法对象; 否则,原始方法对象按原样使用.

所以你得到一个纯粹因为A.前缀的方法.原始函数仍然可以通过方法的im_func(或从2.6开始__func__)属性访问.另请注意,每次访问都会获得一个新方法对象,因此A.b is A.b返回False!

Python 3中,未绑定的方法不再作为单独的类型存在,并且您将从两个打印调用获得相同的输出:

$ python3
Python 3.1.2 (release31-maint, Sep 17 2010, 20:27:33) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class A:
...     def b(self, a):
...         print(a)
...     print(dir(b))
... 
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> print(dir(A.b))
['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
Run Code Online (Sandbox Code Playgroud)

如果你替换dir,id你会发现它在两种情况下都是完全相同的函数对象,在Python 3中.