when a function embedded in class be the "method" of the class?
When this is executed...
class A:
def b(self, a):
print a
print dir(b)
print dir(A.b)
开发者_高级运维
It gives the result:
['__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']
why this differs?
In Python 2, the second case returns an unbound method, and the first case a function. From the documentation, emphasis mine:
User-defined method objects may be created when getting an attribute of a class (perhaps via an instance of that class), if that attribute is a user-defined function object, an unbound user-defined method object, or a class method object. When the attribute is a user-defined method object, a new method object is only created if the class from which it is being retrieved is the same as, or a derived class of, the class stored in the original method object; otherwise, the original method object is used as it is.
So you get a method purely because of the A.
prefix. The original function is still accessible through the im_func
(or from 2.6 onwards also __func__
) attribute of the method. Also note that you get a new method object on every access, so A.b is A.b
returns False
!
In Python 3, unbound methods don't exist as a separate type anymore, and you will get the same output from both print calls:
$ 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__']
If you replace dir
by id
you will see that it is the exact same function object in both cases, in Python 3.
精彩评论