Добавление метода к существующему экземпляру объекта
Предисловие - примечание 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
Добавление метода к существующему экземпляру объекта
Мы используем файлы cookies для улучшения работы сайта. Оставаясь на нашем сайте, вы соглашаетесь с условиями использования файлов cookies. Чтобы ознакомиться с нашими Положениями о конфиденциальности и об использовании файлов cookie, нажмите здесь.