В чем разница между функцией, несвязанным методом и связанным методом?


Я задаю этот вопрос из-за обсуждения темы комментариев этого ответа. Я на 90% пути, чтобы получить мою голову вокруг него.

In [1]: class A(object):  # class named 'A'
   ...:     def f1(self): pass
   ...:
In [2]: a = A()  # an instance

f1 существует в трех различных формах:

In [3]: a.f1  # a bound method
Out[3]: <bound method a.f1 of <__main__.A object at 0x039BE870>>
In [4]: A.f1  # an unbound method
Out[4]: <unbound method A.f1>
In [5]: a.__dict__['f1']  # doesn't exist
KeyError: 'f1'
In [6]: A.__dict__['f1']  # a function
Out[6]: <function __main__.f1>

в чем разница между связанный метод,несвязанный метод и функции объекты, все из которых описаны f1? Как можно назвать эти три объекта? Как они могут быть преобразованы друг в друга? Этот документация на этом материале довольно трудно понять.

5   51   2012-08-14 13:53:23

5 ответов:

A функции создано def заявление, или lambda. Под Python 2, когда функция появляется в теле class оператор (или передается в type вызов конструкции класса), он преобразуется в несвязанный метод. (Python 3 не имеет несвязанных методов; см. ниже.) Когда функция доступна в экземпляре класса, она преобразуется в связанный метод, который автоматически предоставляет экземпляр метод как первый

довольно трудно понять

Ну, это довольно сложная тема, и она имеет отношение к дескрипторам.

начнем с функции. Здесь все понятно-вы просто вызываете его, все предоставленные аргументы передаются при его выполнении:

>>> f = A.__dict__['f1']
>>> f(1)
1

обычный TypeError возникает в случае любой проблемы с количеством параметров:

>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f1() takes exactly 1 argument (0 given)

теперь, методов. Методы-это функции, с небольшим количеством специй. Дескрипторы заходите в игру сюда. Как описано в Модель Данных,A.f1 и A().f1 переведен в A.__dict__['f1'].__get__(None, A) и type(a).__dict__['f1'].__get__(a, type(a)) соответственно. И результаты эти __get__ ' ы отличаются от raw и None:

>>> f.im_self is None
True

в случае bound method эта логика сразу же поставляет оригинал f1 С A он был создан (этот экземпляр хранится в ):

>>> f = A().f1
>>> f.im_self
<__main__.A object at 0x800f23950>
>>> f()
<__main__.A object at 0x800f23950>

и bound означает, что базовая функция привязана к некоторому экземпляру. unbound означает, что он все еще связан, но только с a класс.

объект функции-это вызываемый объект, создаваемый определением функции. Как связанные, так и несвязанные методы являются вызываемыми объектами, созданными дескриптором, вызываемым двоичным оператором dot.

связанные и несвязанные объекты метода имеют 3 основных свойства:im_func - Это объект функции, определенный в классе,im_class - это класс, и im_self - это экземпляр класса. Для несвязанных методов,im_self и None.

когда связанный метод вызывается, он вызывает im_func с im_self в качестве первого параметра следовали его вызывающие параметры. несвязанные методы вызывают базовую функцию только с ее вызывающими параметрами.

одна интересная вещь, которую я видел сегодня, заключается в том, что когда я назначаю функцию члену класса, он становится несвязанным методом. Например:

class Test(object):
    @classmethod
    def initialize_class(cls):
        def print_string(self, str):
            print(str)
        # Here if I do print(print_string), I see a function
        cls.print_proc = print_string
        # Here if I do print(cls.print_proc), I see an unbound method; so if I
        # get a Test object o, I can call o.print_proc("Hello")

пожалуйста, обратитесь к Python 2 и Python 3 документация для получения более подробной информации.

моя интерпретация заключается в следующем.

класс Function фрагменты:

Python 3:

class Function(object):
    . . .
    def __get__(self, obj, objtype=None):
        "Simulate func_descr_get() in Objects/funcobject.c"
        if obj is None:
            return self
        return types.MethodType(self, obj)

Python 2:

class Function(object):
    . . .
    def __get__(self, obj, objtype=None):
        "Simulate func_descr_get() in Objects/funcobject.c"
        return types.MethodType(self, obj, objtype)
  1. если функция вызывается без класса или экземпляра, это обычная функция.
  2. если функция вызывается из класса или экземпляра, его __get__ - это вызывается для получения обернутой функции:
    а. B.x такой же, как B.__dict__['x'].__get__(None, B). В Python 3 это возвращает простую функцию. В Python 2, это возвращает несвязанные функции.

    b.b.x такой же, как type(b).__dict__['x'].__get__(b, type(b). Это вернет связанный метод как в Python 2, так и в Python 3, Что означает self будет неявно передается в качестве первого аргумента.