2013-11-10 2 views
5

При чтении о unification of types я наткнулся на то, что встроенных типов имеют method_descriptor s и builtin_function_or_method s вместо method s и function s, почему?несогласованности среди встроенных типов и определяемых пользователем

>>> 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'> 

Там нет никаких оснований для class A к подклассу список, я просто хотел показать, что типы отличаются.

ответ

3

Разница на самом деле заключается в том, что встроенные функции являются С-скомпилированными дескрипторами кода, тогда как пользовательские функции представляют собой код, заданный пользователем descriptors. См. source.

Кроме того, в то время как встроенные и их методы являются статически распределенными структурами данных, память для пользовательских структур данных распределяется динамически. Даже размеры отличаются: размер дескрипторов равный среди встроенных функций, а также среди подобной определенного пользователя, обратитесь к источнику С (ссылки выше):

>>> 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 

Таким образом эти вещами неповторимой, пребывают в разных местах и ведут себя по-другому. Нет необходимости давать им равные имена.

Я хотел бы добавить пропущенный скомпилированный аналог для classmethod, classmethod_descriptor,

>>> type(float.__dict__['fromhex']) 
<type 'classmethod_descriptor'> 

и некоторые другие интересные виды:

>>> type(A.__init__) 
<type 'wrapper_descriptor'> 
>>> type(A.__dict__['__dict__']) 
<type 'getset_descriptor'> 

См:

  1. What is a wrapper_descriptor, and why is Foo.__init__ one in this case
  2. What is the __dict__.__dict__ attribute of a Python class?
+0

Благодарим за ответ. Я понимаю, что существует разница в реализации, но я хочу знать, почему эти методы должны быть разных типов. Есть ли причина совместимости, или это просто закончилось тем, что было таким, и не создавало никаких проблем? –

+0

@ hack.augusto Я попытался добавить еще несколько объяснений, посмотреть, помогает ли это – alko

+0

отличный ответ, спасибо –

Смежные вопросы