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

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

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

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

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

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

Я oo этого не рекомендую. Это object-oriented плохая идея. Не делай этого.

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

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

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

Foo.sample_method = sample_method

Поскольку method это поучительно, я покажу method вам несколько способов сделать python это.

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

Вот код настройки. Нам oops нужно определение класса. Его oop можно импортировать, но это python-interpreter не имеет значения.

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

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

foo = Foo()

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

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

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

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

foo.sample_method = sample_method.__get__(foo)

а pythonic теперь:

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

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

Сначала импортируем python типы, из которых мы получим pythonista конструктор метода:

import types

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

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

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

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

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

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

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

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

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

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

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

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

Если мы попытаемся method добавить sample_method таким python-shell же образом, как мы могли py бы добавить его в класс, он method не будет связан с экземпляром object-oriented и не будет принимать неявное pythonista 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)

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

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

Заключение

Теперь вы знаете oops несколько способов сделать method это, но, если серьезно, не method делайте этого.

python

oop

methods

monkeypatching

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