Я хотел бы реализовать класс пересылки в Python, реализуя некоторый базовый класс, который принимает в своем конструкторе другую реализацию одного и того же базового класса и пересылает этот класс для каждого метода в базовом классе.Какое простейшее определение класса пересылки в Python?
Это может быть полезно для предоставления точки настройки, добавления кеширования для определенных методов, ведения журнала по каждому сайту вызова и тому подобного.
Это просто написать это вручную. С учетом этого базового класса:
class BaseClass(object):
def method_a(self, *args):
pass
@property
def prop_b(self):
pass
def method_c(self, a, b, **kwargs):
pass
Вот простая реализация пересылки.
class ForwardBaseClass(BaseClass):
def __init__(self, underlying_implementation):
self._impl = underlying_implementation
def method_a(self, *args):
return self._impl.method_a(*args)
@property
def prop_b(self):
return self._impl.prop_b
def method_c(self, a, b, **kwargs):
return self._impl.method_c(a, b, **kwargs)
Обратной просто писать код, что есть много шаблонного кода, и что код должен быть написан для каждого метода. Поскольку методы добавляются в базовый класс, аналогичный код должен быть добавлен в класс пересылки; и если изменения желательны в том, как класс выполняет свою переадресацию, они должны быть распределены по всем методам. (Предположим, например, что мы хотели изменить класс, чтобы он использовал менеджер контекста, который он использовал для каждого вызова.)
Есть ли короткий, Pythonic способ сделать это, либо на базовом языке, с встроенных модулей или с некоторым надежным модулем на PyPI?
Желаемых характеристики:
- Точных сигнатуры методов
- Перенаправленная подпись должна соответствовать базовому классу
- Нет
*args, **kwargs
на каждую подписи
- Методы с
@property
декоратором обернуты надлежащим образом __<method>__
методы, если они существуют, завернутые правильно- Отсутствия дополнительных затрат на вызов метода по прямым вперед реализациям
dir(instance)
делает то же самое, как прямой вперед реализация
Приятно иметь:
- сообщения об ошибках, когда базовый класс не удовлетворяет некоторым необходимым критериям
- Значимые строки документации
- Возможности вывести из полученного объекта
- Методы с
@staticmethod
декоратором направляется к классу переданным в реализации - Методы с
@classmethod
декоратором пересылаемых к классу пройденного в реализации __init__
и__new__
не пересылаются
Места, где есть вероятность дополнительная сложность:
- Базовый класс имеет метакласса
- Базовый класс имеет несколько базовых классов своей собственной
- Некоторые из более эзотерических
__<method>__
с и их семантика
Не волнует:
- Несколько базовых классов
- Декораторы декоративных декоративных элементов, отличные от ,
@staticmethod
, и@classmethod
- Изменение в базовый класс после создания класса экспедиторской
вы можете использовать 'getattr' для пересылки всего, кроме' __init__' и '__new__' (и других вещей, которые вы не хотите) для' self._impl'. это может быть не все ваши желаемые свойства, хотя ... –
Я сомневаюсь, что есть короткий, Pythonic или иначе способ сделать это, честно говоря! – jonrsharpe
В частности, «Никакая дополнительная стоимость за вызов метода за прямолинейную реализацию», похоже, трудно удовлетворить, по крайней мере, если вы хотите поймать всевозможные странные ситуации. Решение, которое вы предлагаете, например, перенаправляет вызовы на объект 'self._impl' - этот дополнительный вызов несет дополнительную плату за вызов. Также требование для 'dir (instance)' to work означает еще одну работу, которая может повредить стоимость вызова. – skyking