В чем разница между функцией, несвязанным методом и связанным методом?
Я задаю этот вопрос из-за обсуждения темы комментариев этого ответа. Я на 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 ответов:
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)
- если функция вызывается без класса или экземпляра, это обычная функция.
если функция вызывается из класса или экземпляра, его
__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будет неявно передается в качестве первого аргумента.
Comments