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

时间:2010-11-28 11:18:51

标签: python

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

class A:
    def b(self, a):
        print a
    print dir(b)
print dir(A.b)

它给出了结果:

['__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']

为什么会有所不同?

1 个答案:

答案 0 :(得分:7)

Python 2 中,第二种情况返回一个未绑定的方法,第一种情况是一个函数。来自the documentation,强调我的:

  

当获取类的属性时(可能通过该类的实例),如果该属性是用户定义的函数对象,未绑定的用户,则可以创建用户定义的方法对象 - 定义的方法对象或类方法对象。当属性是用户定义的方法对象时,仅当从中检索它的类与存储在原始方法对象中的类相同或派生类时,才会创建新的方法对象;否则,原始方法对象按原样使用。

所以你得到的方法完全是因为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__']

如果将dir替换为id,您将在Python 3中看到它与两种情况下完全相同的函数对象。