2014-11-04 85 views
2

我在一系列類方法中有一個冗長的try/except1/except2/etc塊的重複集,這些方法僅在外部類實例上調用的外部類方法不同。下面是一個簡化版本(實際上有4個例外,我處理和八種方法,只有通過實例方法不同,被稱爲):在python 2.7中,如何包裝類實例方法或用try/except塊來裝飾它?

class MyClass(object): 
    def __init__(self): 
     self.arg = 'foo' 

    def method1(self, arg1): 
     err = -1 
     y = None 
     try: 
      x = AnOutsideClass(self.arg)  # Creates a class instance of an imported class 
      y = x.outsideclassmethod1(arg1) # Calls an instance method that returns another different class instance 
     except MyException1: 
      x.dosomething() # Needed to handle error 
     except MyException2: 
      err = 0 
     finally: 
      del x 
     return y, err 

    def method2(self, arg1, arg2, arg3): 
     err = -1 
     y = None 
     try: 
      x = AnOutsideClass(self.arg) 
      y = x.outsideclassmethod2(arg1, arg2, arg3) # This is the only thing changed 
                 # A different method with different argument requirements 
     except MyException1: 
      x.dosomething() 
     except MyException2: 
      err = 0 
     finally: 
      del x 
     return y, err 

    def method3 ... 

我一直在努力試圖通過包裝冷凝這段代碼的多種方式代碼中try:部分中的兩個語句通過使用嵌套函數,裝飾器等,但似乎失敗,因爲我無法翻譯其他例子,這是由於:1)創建需要的類實例稍後會在其中一個except塊中使用,以及2)調用一個實例方法,3)我需要返回實例方法的結果。

無論如何用functools或描述符或任何其他方式完成此部分?我有一個笨拙的實現,目前有一個擴展的if/elif塊,它根據我在包裝函數中使用的整數代碼選擇實例方法,但我認爲必須有更優雅的方式。我相對比較新的Python,並且不知所措...

回答

2

您可以使用函數工廠(即返回函數的函數)。

def make_method(methname): 
    def method(self, *args): 
     err = -1 
     y = None 
     try: 
      x = AnOutsideClass(self.arg)  # Creates a class instance of an imported class 
      y = getattr(x, methname)(*args) # Calls an instance method that returns another different class instance 
     except MyException1: 
      x.dosomething() # Needed to handle error 
     except MyException2: 
      err = 0 
     finally: 
      del x 
     return y, err 
    return method 

class MyClass(object): 
    def __init__(self): 
     self.arg = 'foo' 
    method1 = make_method('outsideclassmethod1') 
    method2 = make_method('outsideclassmethod2') 

make_method作爲字符串傳遞外部方法名稱。使用 getattr(在method之內)從x得到字符串methname的實際方法。 getattr(x, 'foo')相當於x.foo

* in def method(self, *args)告訴Python,method可以接受任意數量的位置參數。 Inside methodargs是一個元組。在中的*告訴Python將args中的元素作爲單個參數傳遞給由getattr(x, methname)返回的方法。在the docs, herethis blog中解釋瞭解包運算符*