使用python装饰器进行代码重构?

Tho*_*fin 4 python refactoring decorator

我实际上正在努力处理一些代码.我知道它可以重构,但我找不到漂亮的智能优雅的解决方案.

这里有两个函数(我的代码中有更多类似的函数):

def fooA(param1, param2):
    if param2 == True:
       code_chunk_1

    fooA_code  #uses only param1

    if param2 == True:
       code_chunk_2


def fooB(param1, param2):
    if param2 == True:
       code_chunk_1

    fooB_code  #uses only param1

    if param2 == True:
       code_chunk_2
Run Code Online (Sandbox Code Playgroud)

我的第一个想法是使用这个装饰器:

def refactorMe(func):
    def wrapper(*args):
        if args[-1]:
            code_chunk_1

        func(*args)

        if args[-1]:
            code_chunk_2

    return wrapper
Run Code Online (Sandbox Code Playgroud)

最后:

@refactorMe
def fooA(param1, param2):
    fooA_code  #uses only param1

@refactorMe
def fooB(param1, param2):
    fooB_code  #uses only param1
Run Code Online (Sandbox Code Playgroud)

不幸的是,我对这个解决方案不满意:

  • 这个装饰器是"侵入式"的,并且特定于fooA和fooB功能
  • param2不再在fooA和fooB体中使用,但我们必须将它保留在函数签名中

也许我没有将装饰器用于其最初目的?

有没有其他方法来重构代码?

非常感谢!

Ned*_*der 6

怎么样:

def call_one(func, param1, param2):
    if param2:
        code_chunk_1

    func(param1)

    if param2:
        code_chunk_2

def _fooA(param1):
    fooA_code  #uses only param1

def _fooB(param1):
    fooB_code  #uses only param1

def fooA(param1, param2):
    call_one(_fooA, param1, param2)

def fooB(param1, param2):
    call_one(_fooB, param1, param2)
Run Code Online (Sandbox Code Playgroud)


Fer*_*yer 5

由于尝试启用某些包装器功能,如果传递的选项为True,请考虑使用关键字参数.这是一个真实的示例,如果请求将代码包装在(database-)事务中:

def wrap_transaction(func):
    def wrapper(*args, **kwargs):
        # If the option "use_transaction" is given, wrap the function in
        # a transaction.  Note that pop() will remove the parameter so
        # that it won't get passed to the wrapped function, that does not need
        # to know about its existance.
        use_transaction = kwargs.pop('use_transaction', False)

        if use_transaction:
            get_connection().begin_transaction()

        try:
            result = func(*args, **kwargs)
        except:
            if use_transaction:
                get_connection().rollback()
            raise

        if use_transaction:
            get_connection().commit()

        return result

    return wrapper

@wrap_transaction
def my_func(param):
    # Note that this function knows nothing about the 'use_transaction' parameter
    get_connection().exec("...")


# Usage: Explicitely enabling the transaction.
my_func(param, use_transaction=True)
Run Code Online (Sandbox Code Playgroud)