Где пример метода декоратора?

В моем коде у меня есть метод, который возвращает экземпляр класса, например:

class MyClass:
  def fun( self, *args ): # the method
    return Props( self, *args )

class Props: # the returned object
  def __init__( self, parent, *args ):
    self.parent = parent
    self.args = args

Чтобы держать вещи организованными, я собираюсь разместить Реквизит в MyClass. Затем я бы хотел обойти забаву и напрямую сделать класс методом экземпляра MyClass, например так:

class MyClass:
  @instancemethod # does not exist!
  class fun:
    def __init__( self, parent, *args ):
      self.parent = parent
      self.args = args

Обратите внимание на комментарий - экземпляр метода декоратора не существует.

Есть ли способ сделать это, то есть превратить вызываемый объект в метод экземпляра? Если я изменю @instancemethod на @classmethod, конструкция сработает, за исключением того, что, конечно, parent - это класс, а не экземпляр. Я удивлен, что не могу найти ничего о том, что кажется противоположной операцией.

Любопытно, чтобы это прояснилось!

Редактировать:

Похоже, мой вопрос был неясен. У меня есть функция-член, забавная, которая возвращает не одно значение или кортеж, а объект, полный данных. Эти данные генерируются на основе содержимого объекта MyClass и аргументов функции. Мой исходный код делает именно то, что я хочу. Второй код - это то, как я предпочел бы написать это.

Более того, я заметил, что декоратор, который я ищу, это просто следующее:

def instancemethod( cls ):
  def f( *args ):
    return cls( *args )
  return f

Это, конечно, идентично "веселому" методу, который я стремился обойти. Также обратите внимание, что тривиальные return cls не идентичны, хотя на первый взгляд может показаться, что это так.

С этим декоратором мое определение второго класса является допустимым и дает желаемый результат, а именно, a.fun() возвращает объект, который (потенциально) инициализируется на основе данных в:

a = MyClass()
p = a.fun(1,2,3)

print a        # <__main__.MyClass instance at 0xb775b84c>
print p.parent # <__main__.MyClass instance at 0xb775b84c>
print p.args   # (1, 2, 3)

Это все еще оставляет меня с вопросом, если метод instance, определенный здесь, не доступен как встроенный в python, потому что он кажется упущением рядом с classmethod и staticmethod. Но, если нет, я полагаю, я могу жить с этой конструкцией.

3 ответа

Я думаю, что вы слишком усложняете вещи без причины; возможно, вы привыкли к другим языкам и хотите перенести свои привычки оттуда.

IIUC, вы намерены сделать что-то вроде:

class SomeClass:
    # typical stuff
    def __init__(self, other, arg1, arg2, arg3, arg4):
        self.parent= other
        # blah blah

class SomeOtherClass:
    # initialize in __init__, setup stuff
    def __init__(self, initarg1, initarg2):
        self.initarg1= initarg1
        self.initarg2= initarg2

    def fun(self, arg3, arg4):
        # return an instance of SomeClass based on
        # initargs and arguments
        return SomeClass(self, self.initarg1, self.initarg2, arg3, arg4)

Я не совсем уверен, что вы пытаетесь сделать, но я подозреваю, что вы хотите прочитать дескрипторы.

По сути, дескриптор является атрибутом класса, который сам по себе является классом, который определяет __get__ а также __set__ методы. В вашем случае вы можете переместить код из Props.__init__ в Props.__set__, задавать Props как fun атрибут класса, и все должно работать так, как вы хотите.

Вы не нуждаетесь в декораторе метода экземпляра, это может работать:

class MyClass:
  class fun:
    def __init__( self, parent, *args ):
      self.parent = parent
      self.args = args

m = MyClass()
f = m.fun(None, 1, 2, 3)
print f.args

Вы также можете изменить свой первый пример на

class Props:
    def __init__( self, parent, *args ):
        self.parent = parent
        self.args = args


class MyClass:
    fun = Props

m = MyClass()
f = m.fun(None, 1, 2, 3)
print f.args
Другие вопросы по тегам