在python 2.7中,如何包装类实例方法或用try / except块装饰它?

时间:2014-11-04 21:27:50

标签: python-2.7 wrapper decorator try-except instance-methods

我在一系列类方法中有一组重复的try / except1 / except2 / etc块,只有在外部类实例上调用外部类方法才有所不同。下面是一个简化版本(我实际上有4个例外处理,8个方法只是被调用的实例方法不同):

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)我需要返回实例方法的结果。 / p>

无论如何使用functools或描述符或任何其他手段来完成此操作?我有一个笨重的实现,目前有一个扩展的if / elif块,它基于我在包装器函数中使用的整数代码来选择实例方法,但我认为必须有一个更优雅的方式。我对Python比较陌生,而且不知所措......

1 个答案:

答案 0 :(得分: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

*中的def method(self, *args)告诉Python method可以接受任意数量的位置参数。 在method内,args是一个元组。 *中的y = getattr(x, methname)(*args)告诉Python将args中的元素作为getattr(x, methname)返回的方法的单个参数传递。 the docs, here以及this blog中解释了*解包运算符。