Bound method python что это

Связанные и несвязанные методы

Несвязанные методы класса — это методы без аргумента self.

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

Связанные методы экземпляра — пара self + функция.

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

И несвязанные методы класса, и связанные методы экземпляра — объекты (так же, как числа и строки) и могут передаваться в виде аргументов (так же как числа или строки). При запуске оба требуют экземпляр в первом аргументе (self).

При вызове связанного метода интерпретатор автоматически подставляет первым аргументом экземпляр, который использовался для создания объекта связанного метода.

class Spam: def doit(self, message): print(message) object1 = Spam() object1.doit('hello world') 

На самом деле создается объект связанного метода object1.doit , в который упакованы вместе экземпляр object1 и метод Spam.doit .

Можно присвоить этот объект переменной и использовать переменную для вызова, как простую функцию:

x = object1.doit # Объект связанного метода: экземпляр+функция x('hello world') # То же, что и object1.doit('. ') 

Вызовем метод через имя класса:

object1 = Spam() t = Spam.doit # Объект несвязанного метода t(object1, 'howdy') # Передать экземпляр в первый аргумент 

self.method — это объект связанного метода экземпляра, так как self — объект экземпляра.

class Eggs: def m1(self, n): print(n) def m2(self): x = self.m1 # Еще один объект связанного метода x(42) # Выглядит как обычная функция Eggs().m2() # Выведет 42 

В Python 3 несвязанные методы — это функции

В Python 3 можно в классе создавать методы без аргумента self и не писать декоратор @staticmethod.

class A(object): def __init__(self, x): self.x = x def __str__(self): return str(self.x) @staticmethod def new_A(s): t = A(int(s)) return t @staticmethod def common_foo(x, k): return x * k def a_foo(self, k): self.x = __class__.common_foo(self.x, k) def func_foo(x, k): return x * k def a_func_foo(self, k): self.x = __class__.func_foo(self.x, k) a1 = A(1) print('a1 =', a1) a2 = A.new_A("2") print('a2 =', a2) z = A.common_foo(3, 4) print('z =', z) a1.a_foo(5) print('a1 =', a1) z = A.func_foo(3, 4) print('z =', z) a1.a_func_foo(5) print('a1 =', a1) 

Использование декоратора @staticmethod повышает читаемость кода.

Связанные методы и другие вызываемые объекты

Связанные методы экземпляра класса — это объекты, которые хранят и экземпляр, и метод. Их можно использовать как обычные функции:

>>> class Number: . def __init__(self, base): . self.base = base . def double(self): . return self.base * 2 . def triple(self): . return self.base * 3 . >>> x = Number(2) # Объекты экземпляров класса >>> y = Number(3) # Атрибуты + методы >>> z = Number(4) >>> x.double() # Обычный непосредственный вызов 4 >>> acts = [x.double, y.double, y.triple, z.double] # Список связанных методов >>> for act in acts: # Вызовы откладываются . print(act()) # Вызов как функции . 4 6 9 8 

Можно посмотреть на атрибуты, которые дают доступ к объекту экземпляра и к методу:

>>> bound = x.double >>> bound.__self__, bound.__func__ (0x0278F610>, 0x027A4ED0>) >>> bound.__self__.base 2 >>> bound() # Вызовет bound.__func__(bound.__self__, . ) 4 

Можно обрабатывать одинаково:

  • функции, определенные через def или lambda;
  • экземпляры, наследующие метод __call__;
  • связанные методы экземпляров.
>>> def square(arg): . return arg ** 2 # Простые функции (def или lambda) . >>> class Sum: . def __init__(self, val): # Вызываемые экземпляры . self.val = val . def __call__(self, arg): . return self.val + arg . >>> class Product: . def __init__(self, val): # Связанные методы . self.val = val . def method(self, arg): . return self.val * arg . >>> sobject = Sum(2) >>> pobject = Product(3) >>> actions = [square, sobject, pobject.method] # Функция, экземпляр, метод >>> for act in actions: # Все 3 вызываются одинаково . print(act(5)) # Вызов любого вызываемого . # объекта с 1 аргументом 25 7 15 >>> actions[-1](5) # Индексы, генераторы, отображения 15 >>> [act(5) for act in actions] [25, 7, 15] >>> list(map(lambda act: act(5), actions)) [25, 7, 15] 

Класс — тоже вызываемый объект. Но он вызывается для создания экземпляра:

>>> class Negate: . def __init__(self, val): # Классы - тоже вызываемые объекты . self.val = -val # Но вызываются для создания объектов . def __repr__(self): # Реализует вывод экземпляра . return str(self.val) . >>> actions = [square, sobject, pobject.method, Negate] # Вызвать класс тоже можно >>> for act in actions: . print(act(5)) . 25 7 15 -5 >>> [act(5) for act in actions] # Вызовет __repr__, а не __str__! [25, 7, 15, -5] 

Посмотрим, какие это объекты:

>>> table = # генератор словарей >>> for (key, value) in table.items(): . print(' => '.format(key, value)) . -5 => 25 => 15 => > 7 =>

Связанные методы и callback

Пример использования связанных методов — GUI на tkinter.

Читайте также:  Find python path mac

Везде, где можно использовать функцию, можно использовать связанный метод.

Можно написать через функцию (или лямбда-выражение):

def handler(): . сохраняет информацию о состоянии в глобальных переменных. . widget = Button(text='spam', command=handler) 

Можно использовать связанный метод:

class MyWidget: def handler(self): . сохраняет информацию о состоянии в self.attr. def makewidgets(self): b = Button(text='spam', command=self.handler) 

self.handler — объект связанного метода. В нем хранятся self и MyWidget.handler. Так как self ссылается на оригинальный экземпляр, то потом, когда метод handler будет вызван для обработки событий, у него будет доступ к экземпляру и его атрибутам (где можно хранить информацию о состоянии объекта между событиями).

Еще один вариант хранения информации между событиями — переопределение метода __call__ (см. перегрузку операторов).

results matching » «

No results matching » «

Источник

Еще немного о дескрипторах в Python

Не так давно на Хабре уже был перевод статьи Раймонда Хеттингера Руководство к дескрипторам. В этой статье я постараюсь рассмотреть вопросы, которые возникли у меня после прочтения. Будет немного примеров кода, собственно вопросов и ответов к ним. Для понимания того, о чем речь, вам нужно знать, что такое дескрипторы и зачем они.

Когда вызываются дескрипторы?

>>> class M(type):
. def __new__(cls, name, bases, dct):
. dct[‘test’] = lambda self, x: x*2
. return type.__new__(cls, name, bases, dct)
.
>>> class A(object):
. def __init__(self):
. self.__dict__[‘test2’] = lambda self, x: x*4
. __metaclass__ = M
.
>>> A().test(2)
4
>>> A().test2(2)
Traceback (most recent call last):
File » < stdin >«, line 1, in < module >
TypeError: < lambda >() takes exactly 2 arguments (1 given)

* This source code was highlighted with Source Code Highlighter .

Что не так? Вроде добавляем функцию одинаково, используя словарь объекта. Почему не вызывается дескриптор для функции «test2»? Дело в том, что функция «test» определяется для словаря класса, а функция «test2» — для словаря объекта:

>>> ‘test’ in A.__dict__
True
>>> ‘test2’ in A.__dict__
False
>>> ‘test’ in A().__dict__
False
>>> ‘test2’ in A().__dict__
True

* This source code was highlighted with Source Code Highlighter .

Читайте также:  Python boolean not true

Отсюда — первый ответ: функция «__get__» вызывается только для дескрипторов, которые являются свойствами класса, а не свойствами объектов этого класса.

Что является дескриптором?

Предыдущий ответ сразу вызывает вопрос — что значит «только для дескрипторов»? Я ведь не создавал никаких дескрипторов, я создал только функцию!

Ответ ожидаемий — функции в Питоне являются дескрипторами(если быть точнее — дескрипторами не данных):

* This source code was highlighted with Source Code Highlighter .

Bound/Unbound методы

И напоследок самое вкусное. Задача:

Есть объект некоего класса, к которому необходимо динамически добавить метод, которому, конечно, должен передаваться «self» параметр. Не представляется возможным добавлять этот метод в словарь класса (мы не хотим повлиять на другие объекты).

>>> class A(object):
. def __init__(self):
. self.x = 3
.
>>> def add_x(self, add):
. self.x += add
. print ‘Modified value: %s’ % (self.x,)
.
>>> a = A()
>>> a.add_x = add_x
>>> a.x
3
>>> a.add_x(3)
Traceback (most recent call last):
File » < stdin >«, line 1, in < module >
TypeError: add_x() takes exactly 2 arguments (1 given)

* This source code was highlighted with Source Code Highlighter .

Получаем ожидаемую ошибку, которая подтверждает первый ответ — при обращении к свойству-дескриптору объекта не используется «__get__». Что же делать?

Поиграем немного с методом «__get__» функции, которую мы только что создали:

* This source code was highlighted with Source Code Highlighter .

О, кажется это то, что нам надо! В предпоследней строчке мы получили «bound» метод — именно так смотрелся бы вызов «A().add_x», если в классе «A» был бы определен метод «add_x». А в последней строчке видим «ожидаемый» результат вызова «A.add_x». Теперь мы знаем, как добавить метод к объекту:

* This source code was highlighted with Source Code Highlighter .

Бинго!
И так, именно метод «__get__» для функций-дескрипторов создает «bound/unbound» методы классов и объектов. И нет здесь никакой магии 🙂

Литература

Что еще почитать? На самом деле — немного. Есть несколько глав, в которых рассказывается о дескрипторах, в Python Data Model (implementing-descriptors), ну и можно снова вспомнить действительно хорошую статью Хеттингера (оригинал).

P.S. Русский — не родной язык, замечания прошу в личку.

Источник

Bound, unbound, and static methods in Python

Methods in Python are like functions except that it is attached to an object.The methods are called on objects and it possibly make changes to that object. These methods can be Bound, Unbound or Static method. The static methods are one of the types of Unbound method. These types are explained in detail below.

Читайте также:  Королевский питон длина тела

Bound methods

If a function is an attribute of class and it is accessed via the instances, they are called bound methods. A bound method is one that has ‘ self ‘ as its first argument. Since these are dependent on the instance of classes, these are also known as instance methods.

Need for these bound methods

The methods inside the classes would take at least one argument. To make them zero-argument methods, ‘ decorators ‘ has to be used. Different instances of a class have different values associated with them.

For example, if there is a class “Fruits”, and instances like apple, orange, mango are possible. Each instance may have different size, color, taste, and nutrients in it. Thus to alter any value for a specific instance, the method must have ‘self’ as an argument that allows it to alter only its property.

My name is A from object 1 My name is B from object 2 My name is C from object 2 My name is A from object 1

In the above example two instances namely samp1 and samp2 are created. Note that when the function alterIt() is applied to the second instance, only that particular instance’s value is changed. The line samp1.myFunc() will be expanded as sample.myFunc(samp1). For this method no explicit argument is required to be passed. The instance samp1 will be passed as argument to the myFunc(). The line samp1.myFunc2() will generate the error :

Traceback (most recent call last): File "/home/4f130d34a1a72402e0d26bab554c2cf6.py", line 26, in samp1.myFunc2() #----------> error line TypeError: myFunc2() takes 0 positional arguments but 1 was given

It means that this method is unbound. It does not accept any instance as an argument. These functions are unbound functions.

Unbound methods and Static methods

Methods that do not have an instance of the class as the first argument are known as unbound methods. As of Python 3.0, the unbound methods have been removed from the language. They are not bounded with any specific object of the class. To make the method myFunc2() work in the above class it should be made into a static method

Static methods are similar to class methods but are bound completely to class instead of particular objects. They are accessed using class names.

Need for making a method static

Not all the methods need to alter the instances of a class. They might serve any common purpose. A method may be a utility function also.

For example, When we need to use certain mathematical functions, we use the built in class Math . The methods in this class are made static because they have nothing to do with specific objects. They do common actions. Thus each time it is not an optimized way to write as:

So they can be simply accessed using their class name as Math.ceil(5.23) .

A method can be made static in two ways:

Источник

Оцените статью