2011-12-30 2 views
0

Приносим извинения, если я не выражаю свое ясное понимание. То, что я хочу сделать это:Как реализовать подметод в классе Python?

class someClass(object): 
    def aMethod(self, argument): 
     return some_data #for example a list or a more complex datastructure 
    def aMethod_max(self, argument): 
     var = self.aMethod(argument) 
     #do someting with var 
     return altered_var  

или я мог бы сделать:

def aMethod(self, argument): 
     self.someVar = some_data 
     return some_data #for example a list or a more complex datastructure 
    def aMethod_max(self, argument): 
     if not hasattr(self, someVar): 
      self.aMethod(argument)   
     #do someting with self.var 
     return altered_var 

Но я считал это слишком сложно, и надеялся на более элегантное решение. Надеюсь, теперь ясно, чего я хочу достичь.

Поэтому я фантазировал о чем-то подобном в следующем параграфе.

class someClass(object): 
    someMethod(self): 
     #doSomething 
     return result 
    subMethod(self): 
     #doSomething with the result of someMethod 

Foo = someClass() 
Foo.someMethod.subMethod() 

или если SomeMethod имеет аргумент что-то вроде

Foo.someMethod(argument).subMethod() 

Как бы я сделать что-то подобное в Python?

EDIT: или вот так?

subMethod(self): 
    var = self.someMethod() 
    return doSomething(var) 
+1

jQuery вдохновил Python ... – awesomo

ответ

2

Давайте сравним существующие решения, уже заданные в вашем вопросе (например, те, которые вы называете «сложными» и «неэлегантными») с предложенной вами альтернативой.

Существующие решения означает, что вы сможете написать:

foo.subMethod() # foo.someMethod() is called internally 

но предложил ваша альтернатива означает, что вы должны написать:

foo.someMethod().subMethod() 

, который, очевидно, хуже.

С другой стороны, если subMethod должен быть в состоянии изменить результат любой метод, а не только someMethod, то существующие решения будет означать, вы должны написать:

foo.subMethod(foo.anyMethod()) 

с только недостаток заключается в том, что вы должны ввести foo дважды, в отличие от одного раза.

Заключение: в целом существующие решения являются менее сложными и неэлегантными, чем предлагаемая вами альтернатива - так придерживайтесь существующих решений.

1

Вы можете сделать method chaining когда результат SomeMethod является экземпляром SomeClass.

Простой пример:

>>> class someClass: 
... def someMethod(self): 
...  return self 
... def subMethod(self): 
...  return self.__class__ 
... 
>>> x=someClass() 
>>> x 
<__main__.someClass instance at 0x2aaaaab30d40> 
>>> x.someMethod().subMethod() 
<class __main__.someClass at 0x2aaaaab31050> 
+0

Извините, в моем вопросе не было ясно. Второй метод должен быть способен сделать что-то с результатом первого метода. Например: первый метод возвращает список, а второй метод возвращает результат на основе ввода первого метода. Надеюсь, это объяснит это лучше. – Randomtheories

+0

@Randomories. Тогда ответ отрицательный. Невозможно делать то, что вы описываете, потому что вы можете только цепочки методов возвращаемого объекта. Если вы вернете список, вы можете использовать методы списка цепочек. Если вы вернете строку, вы можете связать строковые методы. Если 'someMethod' возвращает экземпляр' someClass', 'subMethod' не будет доступен для цепочки. – kojiro

+0

@kojiro мне кажется, что вы можете отслеживать изменения в переменной, записывая результаты в экземпляр класса, сохраняя при этом self (таким образом поддерживая свободный интерфейс). Я что-то упускаю? Несмотря на это, это похоже на плохой дизайн API и, вероятно, следует пересмотреть. –

1

Вы можете достичь что-то подобное с помощью декораторов:

def on_result(f): 
    def decorated(self,other,*args,**kwargs): 
     result = getattr(self,other)(*args,**kwargs) 
     return f(result) 
    return decorated 

Использование:

class someClass(object): 
    def someMethod(self,x,y): 
     #doSomething 
     result = [1,2,3,x,y] # example 
     return result 
    @on_result 
    def subMethod(self): 
     #doSomething with the result of someMethod 
     print self # example 

Foo = someClass() 
Foo.subMethod("someMethod",4,5) 

Выход:

[1, 2, 3, 4, 5] 

Как вы видите, первый аргумент - это имя метода, который должен быть привязан, а остальные будут переданы ему, независимо от его подписи.

EDIT: на второй мысли, это довольно бессмысленно, так как вы всегда можете использовать

Foo.submethod(Foo.someMethod(4,5))... 

Может быть, я не понимаю, что вы пытаетесь достичь. Нужно ли связать subMethod с методом ? Или, может быть, это синтаксическая форма

a.b().c() 

Это вам очень понравилось? (В этом случае, см ответ Кодзиро в)

+1

Вопрос в том, чтобы связать аргумент subMethod с результатом someMethod. Кстати: разве это не Foo.submethod (Foo.someMethod (4, 5))? Спасибо вам за мысли. – Randomtheories

1

Не уверен, что если я понять это правильно, но, возможно, вы имеете в виду это:

Foo.subMethod(Foo.someMethod()) 

Это передает результат SomeMethod() в subMethod(). Вам нужно будет изменить текущее определение subMethod(), чтобы принять результат someMethod().

+0

Да, вот что все. Я хотел знать, есть ли другие способы для этого. И, возможно, определить subMethod специально, чтобы принимать только результаты someMethod в качестве аргумента. Извините за путаницу. – Randomtheories

0

С обратной связи до сих пор, я понимаю, что subMethod соединит только к SomeMethod, верно? Может быть, вы можете добиться этого сочетания декоратора с крышкой:

def on_result(other): 
    def decorator(f): 
     def decorated(self,*a1,**k1): 
      def closure(*a2,**k2): 
       return f(self,getattr(self,other)(*a1,**k1),*a2,**k2) 
      return closure 
     return decorated 
    return decorator 

class someClass(object): 
    def someMethod(self,a,b): 
     return [a,2*b] 
    @on_result('someMethod') 
    def subMethod(self,result,c,d): 
     result.extend([3*c,4*d]) 
     return result 

Foo = someClass() 
print Foo.subMethod(1,2)(3,4) # prints [1,4,9,16] 

Декоратор является своим родом «некрасиво», но когда-то написал его использование довольно элегантный ИМХО (плюс, нет контрсил в подписи любого метода) ,

Примечание: Я использую Python 2.5, и это единственный способ, которым я знаю, писать декораторы, которые принимают аргументы. Там, вероятно, лучший способ, но я слишком ленив, чтобы посмотреть его прямо сейчас ...

Смежные вопросы