Добавление метода к существующему экземпляру объекта

Предисловие - примечание pythonista о совместимости: другие ответы python-shell могут работать только в Python oo 2 - этот ответ должен отлично py работать в Python 2 и 3. Если methods вы пишете только Python 3, вы pythonista можете не указывать явное python-shell наследование от object, но в противном methods случае код должен остаться python прежним.

Добавление метода к существующему экземпляру объекта

Я читал, что можно methods добавить метод к существующему oop объекту (например, не в определении python класса) в Python.

Я понимаю, что python-interpreter это не всегда хорошее решение. Но как это сделать?

Да, это возможно - но не рекомендуется

Я method этого не рекомендую. Это oop плохая идея. Не делай этого.

Вот oops несколько причин:

  • Вы добавите связанный объект к каждому экземпляру, с которым вы это делаете. Если вы будете делать это часто, вы, вероятно, потратите много памяти. Связанные методы обычно создаются только на короткое время их вызова, а затем перестают существовать при автоматической сборке мусора. Если вы сделаете это вручную, у вас будет привязка имени, ссылающаяся на связанный метод, что предотвратит его сборку мусора при использовании.
  • Экземпляры объектов данного типа обычно имеют свои методы для всех объектов этого типа. Если вы добавите методы в другом месте, некоторые экземпляры будут иметь эти методы, а другие - нет. Программисты этого не ожидают, и вы рискуете нарушить rule of least surprise.
  • Поскольку есть и другие действительно веские причины не делать этого, вы дополнительно ухудшите себе репутацию, если сделаете это.

Таким образом, я object-oriented-design предлагаю вам не делать этого, если oo у вас нет действительно веской oo причины. Гораздо лучше определить правильный метод в определении класса или меньше, желательно, чтобы oop обезьяна исправляла класс oop напрямую, например:

Foo.sample_method = sample_method

Поскольку python-shell это поучительно, я покажу object-oriented-design вам несколько способов сделать python-interpreter это.

Как это можно сделать

Вот код настройки. Нам ood нужно определение класса. Его py можно импортировать, но это object-oriented не имеет значения.

class Foo(object):
    '''An empty class to demonstrate adding a method to an instance'''

Создайте python экземпляр:

foo = Foo()

Создайте метод python-shell для добавления к нему:

def sample_method(self, bar, baz):
    print(bar + baz)

Method naught (0) - используйте метод дескриптора, __get__

Пунктирный pythonic поиск в функциях вызывает method метод __get__ функции с экземпляром, привязывая object-oriented объект к методу и тем самым oo создавая «связанный метод».

foo.sample_method = sample_method.__get__(foo)

а python-interpreter теперь:

>>> foo.sample_method(1,2)
3

Метод первый - types.MethodType

Сначала импортируем method типы, из которых мы получим object-oriented конструктор метода:

import types

Теперь oop мы добавляем метод к экземпляру. Для pythonista этого нам потребуется конструктор oo MethodType из модуля types (который py мы импортировали выше).

Сигнатура ood аргумента для типов .MethodType oop - (function, instance, class):

foo.sample_method = types.MethodType(sample_method, foo, Foo)

и использование:

>>> foo.sample_method(1,2)
3

Метод второй: лексическая привязка

Сначала pythonista мы создаем функцию-оболочку, которая python связывает метод с экземпляром:

def bind(instance, method):
    def binding_scope_fn(*args, **kwargs): 
        return method(instance, *args, **kwargs)
    return binding_scope_fn

использование:

>>> foo.sample_method = bind(foo, sample_method)    
>>> foo.sample_method(1,2)
3

Метод третий: functools.partial

Частичная method функция применяет первый pythonic аргумент (ы) к функции (и, возможно, аргументы python ключевого слова), и позже py может быть вызвана с оставшимися oop аргументами (и переопределением python-shell аргументов ключевого слова). Таким pythonic образом:

>>> from functools import partial
>>> foo.sample_method = partial(sample_method, foo)
>>> foo.sample_method(1,2)
3    

Это имеет смысл, если object-oriented учесть, что связанные методы python-interpreter являются частичными функциями ood экземпляра.

Несвязанная функция как атрибут объекта - почему это не работает:

Если мы попытаемся method добавить sample_method таким methods же образом, как мы могли method бы добавить его в класс, он pythonista не будет связан с экземпляром oop и не будет принимать неявное python-interpreter self в качестве первого аргумента.

>>> foo.sample_method = sample_method
>>> foo.sample_method(1,2)
Traceback (most recent call last):
  File "", line 1, in 
TypeError: sample_method() takes exactly 3 arguments (2 given)

Мы oop можем заставить несвязанную python-interpreter функцию работать, явно передавая object-oriented экземпляр (или что-то еще, поскольку py этот метод фактически не ood использует переменную аргумента pythonista self), но это не будет согласовано oops с ожидаемой сигнатурой других python-shell экземпляров (если мы как python-shell обезьяны исправляем этот pythonista экземпляр):

>>> foo.sample_method(foo, 1, 2)
3

Заключение

Теперь вы знаете py несколько способов сделать methods это, но, если серьезно, не object-oriented делайте этого.

python

oop

methods

monkeypatching

2022-11-20T00:32:11+00:00