Reputation: 2170
While reading about the unification of types I stumbled on the fact that built-in types have method_descriptor
s and builtin_function_or_method
s instead of method
s and function
s, why?
>>> list.append
<method 'append' of 'list' objects>
>>> type(list.append)
<class 'method_descriptor'>
>>> [].append
<built-in method append of list object at 0x7f0c4214aef0>
>>> type([].append)
<class 'builtin_function_or_method'>
>>> class A(list):
... def append(self): pass
...
>>> A.append
<function A.append at 0x7f0c42168dd0>
>>> type(A.append)
<class 'function'>
>>> A().append
<bound method A.append of []>
>>> type(A().append)
<class 'method'>
There is no good reason for class A
to subclass list, I just wanted to show that the types differ.
Upvotes: 7
Views: 197
Reputation: 48317
Difference lies in fact that built-ins are C-compiled code descriptors, whereas user-defined functions represent iterpreted code descriptors. See source for details.
Also, while built-ins and their methods are statically allocated data structures, memory for user-defined data structures is allocated dinamically. Even sizes differs: size of descriptors is equal among built-in functions as well as among similar user-defined, refer to C source (link above):
>>> sys.getsizeof(list.append)
72 # built-in
>>> sys.getsizeof(dir)
72 # built-in
>>> sys.getsizeof(A.__init__)
80 # class/instance method
>>> sys.getsizeof(lambda x: x)
120 # static function
So those things look different, resides in different places and behave different. There is no need to give them equal names.
I would like to add missed compiled analogue for classmethod
, classmethod_descriptor
,
>>> type(float.__dict__['fromhex'])
<type 'classmethod_descriptor'>
and some other interesting types:
>>> type(A.__init__)
<type 'wrapper_descriptor'>
>>> type(A.__dict__['__dict__'])
<type 'getset_descriptor'>
See:
Foo.__init__
one in this case__dict__.__dict__
attribute of a Python class?Upvotes: 4