В чем разница между "функцией", "методом" и "связанным методом" в Python 3?
Я наблюдал по крайней мере 3 типа, связанных с функциями в Python 3:
>>> class A():
... def f(): pass
...
>>> A.f
<function A.f at 0x7fcaef304268>
>>> A().f
<bound method A.f of <__main__.A object at 0x7fcaef2fae80
>>> set.union
<method 'union' of 'set' objects>
Мне интересно, в чем разница между "функция", "метод" и "связанный метод"? Является ли 'method' типом, эквивалентным 'unbound method' в Python 2?
1 ответ
Является ли 'method' типом, эквивалентным 'unbound method' в Python 2?
Kind-а-рода-а. Но не совсем. Это method_descriptor
объект, определенный в коде C. Это несвязанный метод, но не тот, который вы нашли в Python 2.
Для типов Python, написанных на C, все "методы" на самом деле являются функциями C. <method 'name' of 'type' objects>
объект, который вы нашли, является специальным объектом, который вы можете использовать для вызова этой функции с учетом экземпляра и дополнительных аргументов, как function
Объект делает для пользовательских классов Python. Объект определен в C в PyMethodDescr_Type
структура. Он реализует протокол дескриптора, как и функции.
Python определяет несколько других таких типов дескрипторов; если вы используете __slots__
каждый атрибут является дескриптором типа member_descriptor
(см. PyMemberDescr_Type
структура), в то время как classmethod
, property
а также staticmethod
возможно более известные объекты дескриптора.
В Python 2 связанные и несвязанные методы на самом деле являются только одним типом, instancemethod
(определяется PyMethod_Type
структура); он будет сообщаться как связанный, если __self__
(im_self
) атрибут установлен. В Python 3 использование функции в качестве дескриптора просто не создает объекты методов без __self__
задавать; вместо того, чтобы звонить function.__get__()
без экземпляра просто возвращает функцию снова.
Единственная причина, по которой Python 2 возвращает несвязанные методы, - принудительная проверка типа; первый аргумент должен быть экземпляром класса (или его подклассом). Это не имело особого смысла для кода Python, который поддерживает типизацию с использованием утили, поэтому в Python 3 ограничение было снято. Тем не менее, с кодом C вы не можете использовать duck-typing, вам все равно придется ограничить тип, и поэтому C-типы по- прежнему возвращают method_descriptor
объект, который применяет это ограничение.