где пример метода декоратора? - PullRequest
3 голосов
/ 12 апреля 2011

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

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 - это класс, а не экземпляр. Я удивлен, что не могу найти ничего о том, что кажется противоположной операцией.

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

Edit:

Кажется, мой вопрос был неясным. У меня есть функция-член, забавная, которая возвращает не одно значение или кортеж, а объект, полный данных. Эти данные генерируются на основе содержимого объекта 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)

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

Ответы [ 3 ]

1 голос
/ 12 апреля 2011

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

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

1 голос
/ 05 мая 2011

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

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)
0 голосов
/ 12 апреля 2011

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

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
...