2

I have a repeating set of lengthy try/except1/except2/etc blocks in a series of class methods that only differ by the outside class method being called on an outside class instance. Below is a simplified version (there are actually 4 exceptions that I am handling and eight methods that only differ by the instance method being called):

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

I have been trying various ways of condensing this code by trying to wrap the two statements in the try: portion of the code by using nested functions, decorators, etc, but seem to fail due to the fact that I am have trouble translating other examples of this due to: 1) am creating a class instance that needs to be used later in one of the except blocks and 2) am calling an instance method and 3) I need to return the result of the instance method.

Is there anyway of accomplishing this with partial from functools or descriptors or any other means? I have a clunky implementation currently with an extended if/elif block that picks the instance method based on an integer code that I use in a wrapper function, but am thinking there must be a more elegant way. I am relatively new to Python and am at a loss...

4

1 回答 1

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中获取实际方法。 相当于。xmethnamegetattr(x, 'foo')x.foo

*indef method(self, *args)告诉 Pythonmethod可以接受任意数量的位置参数。里面methodargs是一个元组。*in y = getattr(x, methname)(*args)告诉 Python 将元素作为args单独的参数传递给getattr(x, methname). 解*包运算符在文档、此处此博客中进行了说明。

于 2014-11-04T21:37:41.540 回答