объекты метода против объектов-функций, экземпляры класса Python vs class

Я пытаюсь проверить разницу между атрибутами экземпляра и атрибутами класса, изложенными в выпуске Python 2.7.3 от Nov 01, 2012, глава 9: Классы, последняя строка ( источник ):

Действительные имена методов объекта экземпляра зависят от его класса. По определению все атрибуты класса, являющиеся объектами-объектами, определяют соответствующие методы его экземпляров. Итак, в нашем примере xf является допустимой ссылкой на метод, поскольку MyClass.f является функцией, но xi не является, поскольку MyClass.i не является. Но xf – это не то же самое, что MyClass.f – это объект метода, а не объект функции.

У меня есть это:

class MyClass: """A simple example class""" i = 12345 def f(): return 'hello world' 

Затем я делаю это:

 >>> x = MyClass() >>> xf <bound method MyClass.f of <__main__.MyClass instance at 0x02BB8968>> >>> MyClass.f <unbound method MyClass.f> >>> type(MyClass.f) <type 'instancemethod'> >>> type(xf) <type 'instancemethod'> 

Обратите внимание, что тип xf и MyClass.f является примером. Нет разницы в типах, но в учебнике сказано иначе. Может кто-то прояснить?

Связанные с несвязанными методами – объяснение.

… или почему у Python есть поведение, которое вы указываете.

Итак, во-первых, отметьте, что в 3.x это отличается. В 3.x вы получите MyClass.f как функцию, а xf – как ожидалось. Такое поведение по существу является плохим дизайнерским решением, которое впоследствии было изменено.

Причиной этого является то, что у Python есть концепция метода, который отличается от большинства языков, что по существу является функцией с первым аргументом, предварительно заполненным как экземпляр ( self ). Это предварительное заполнение делает связанный метод .

 >>> x.foo <bound method MyClass.foo of <__main__.MyClass instance at 0x1004989e0>> 

В Python 2.x и ранее было установлено, что метод, не привязанный к экземпляру, будет несвязанным методом , который был функцией с ограничением, что первый аргумент ( self ) должен быть экземпляром объекта. Затем он готов к привязке к экземпляру и станет связанным методом .

 >>> MyClass.foo <unbound method MyClass.foo> 

Со временем стало ясно, что несвязанный метод – это просто функция с этим нечетным ограничением, которое на самом деле не имеет значения (что « self должен быть «правильного» типа), поэтому они были удалены с языка (в 3.x) , Это, по сути, утиная типизация, которая подходит для языка.

 Python 3.3.0 (default, Dec 4 2012, 00:30:24) >>> x.foo <bound method MyClass.foo of <__main__.MyClass object at 0x100858ed0>> >>> MyClass.foo <function MyClass.foo at 0x10084f9e0> 

Дальнейшее чтение.

Это (сжатое, из памяти) объяснение, которое можно полностью прочитать от создателя Python Guido van Rossum в своей серии «История Python» .

Учебник действительно ошибочен; как class.functionname и instance.functionname возвращают объект метода.

__get__ то, что функция является дескриптором, и их метод __get__ вызывается, возвращая метод. Методы имеют атрибут __func__ указывающий на исходную функцию:

 >>> class Foo(object): ... def bar(self): ... pass ... >>> Foo.bar <unbound method Foo.bar> >>> Foo().bar <bound method Foo.bar of <__main__.Foo object at 0x1090d6f10>> >>> # accessing the original function ... >>> Foo.bar.__func__ <function bar at 0x1090cc488> >>> # turning a function back into a method ... >>> Foo.bar.__func__.__get__(None, Foo) <unbound method Foo.bar> >>> Foo.bar.__func__.__get__(Foo(), Foo) <bound method Foo.bar of <__main__.Foo object at 0x1090d6f90>> 

Однако это все изменилось в Python 3; там Foo.bar возвращает сама функция, несвязанные методы больше не существуют:

 $ python3.3 Python 3.3.0 (default, Sep 29 2012, 08:16:08) [GCC 4.2.1 Compatible Apple Clang 3.1 (tags/Apple/clang-318.0.58)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> class Foo: ... def bar(self): ... pass ... >>> Foo.bar <function Foo.bar at 0x105512dd0> >>> Foo.bar.__get__(None, Foo) <function Foo.bar at 0x105512dd0> >>> Foo.bar.__get__(Foo(), Foo) <bound method Foo.bar of <__main__.Foo object at 0x10552fe10>>