class_or_type.descriptor
всегда вызывает descriptor.__get__(None, class_or_type)
, поэтому вы не можете получить __get__
от встроенного объекта несвязанного метода. (Unbound) тип method
, созданный для __get__
в функции Python 2, явно реализует __get__
, потому что методы Python гораздо более гибкие. Таким образом, и builtin.descriptor
, и class.descriptor
вызывают .__get__()
, но тип возвращаемого объекта различен, а для методов Python доступ к атрибуту прокси типа объекта:
Доступ к атрибутам через __dict__
, с другой стороны, никогда не вызывает __get__
, поэтому class_or_type.__dict__['fromkeys']
дает вам исходный объект дескриптора.
Под капотом такие типы, как dict
, включая их методы, реализованы в коде C, не в коде Python , и C гораздо более требователен к типам. Вы никогда не сможете использовать функции, предназначенные для работы с внутренними подробностями реализации dict
объекта со списком, так зачем беспокоиться?
Это действительно все, что нужно сделать; методы для встроенных типов не совпадают с функциями / методами, реализованными в Python, поэтому, хотя они в основном работают одинаково, они не могут работать с динамическими типами, и реализация того, как работают дескрипторы, отражает это.
А так как функции Python (обернутые в методы или нет) могут работать с любым типом Python (если таковой спроектирован), несвязанные method
объекты поддерживают __get__
, так что вы можете взять любой такой объект и прикрепить его к другому классу ; поддерживая __get__
, они поддерживают повторную привязку к новому классу.
Если вы хотите добиться того же самого с типами Python, вам придется обернуть объекты функций в пользовательские дескрипторы, а затем реализовать собственное поведение __get__
, чтобы ограничить то, что приемлемо.
Обратите внимание, что в Python 3 function.__get__(None, classobject)
просто возвращает сам объект функции, а не объект несвязанного метода, как это делает Python 2. Полное различие между несвязанным / связанным методом, когда объекты несвязанного метода ограничивают тип для первого аргумента при вызове, оказалось не таким уж полезным, поэтому оно было отброшено.