питонический способ украшения классометодов - PullRequest
0 голосов
/ 07 мая 2018

Учитывая следующий пример:

class A:
    def f(self, x):
        return 2*x 

Я хотел бы написать другой метод, который использует f выше, но добавляет константу, т.е.

class A:
        def f(self, x):
            return 2*x
        def g(self, x):
            return self.f(x) + 10

Это был бы один из способов. Тем не менее, это очень похоже на украшение! Какой правильный питонский способ сделать это?

Ответы [ 2 ]

0 голосов
/ 07 мая 2018

Расширяя ответ @ Ajax1234, вы можете попробовать: - параметризовать ваш декоратор, - звоните декоратору явно (без @).

def add_val(_value):
  def decorator(f):
    def wrapper(cls, _x):
      return f(cls, _x) + _value
    return wrapper

  return decorator

class A:
  def f(self, x):
    return 2*x 

  g = add_val(10)(f)

[EDIT]

Вы также можете улучшить декоратор с помощью functools.wraps() (который сам является декоратором). Все, что вам нужно сделать, это изменить декларацию оболочки:

@functools.wraps(f)
def wrapper(cls, _x):
  return f(cls, _x) + _value
0 голосов
/ 07 мая 2018

Вы можете написать простую функцию вне класса:

def add_val(f):
  def wrapper(cls, _x):
    return f(cls, _x) + 10
  return wrapper


class A:
  @add_val
  def f(self, x):
    return 2*x 
print(A().f(20))

Выход:

50

Редактировать: вы можете использовать functools.wraps с classmethod в Python3. Обернутая функция f вернет x*2, а декоратор g добавит 10 к возвращенному результату переданной ей функции. Однако, чтобы сохранить исходную функциональность f, вы можете использовать атрибут __wrapped__:

import functools
def g(f):
  @functools.wraps(f)
  def wrapper(cls, _x):
    return f(cls, _x)+10
  return wrapper

class A:
   @classmethod
   @g
   def f(cls, x):
     return x*2

f_1 = functools.partial(A.f.__wrapped__, A)
print(A.f(4))
print(f_1(4))

Выход:

18
8
...