Pythonic将装饰器分配给多个函数的方法是什么?

时间:2018-04-05 23:25:59

标签: python python-3.x loops iteration python-decorators

我需要为多个函数添加一个装饰器 - my_decorator。我没有在每个函数定义的上方添加@my_decorator,而是将其添加到隔离代码块中的所有函数中,因此我将所有内容都集中在一个位置。

有没有干净的Pythonic方法吗?显然我可以做到以下几点,但它有点重复。如果我更改了装饰者名称,我需要在每一行中更新它。

function1 = my_decorator(function1)
function2 = my_decorator(function2)
function3 = my_decorator(function3)

我的第二个想法是将函数放在一个列表中并迭代它,但以下两种方法都不起作用。他们修改每个列表索引的值,同时保持原始函数不变,所以我必须调用,例如function_list[0]()来获取添加了装饰器的函数。

# approach one - a list comprehension
function_list = [function1, function2, function3]
function_list = [my_decorator(function) for function in function_list]

# approach two - a for loop
function_list = [function1, function2, function3]
for index in range(len(function_list)):
    function_list[index] = my_decorator(function_list[index])

我终于找到了一种有效的方法,但使用exec()似乎并不是Pythonic,所以我想知道是否有更好的方式。

function_list = ['function1', 'function2', 'function3']
for index in range(len(function_list)):
    exec("{0} = my_decorator({0})".format(function_list[index]))

以下是我正在测试此代码的代码,它将添加一个装饰器,用于打印" Hello"在调用函数之前:

def my_decorator(function):
    def wrapper(*args, **kwargs):
        print("Hello!", end=' ')
        return function(*args, **kwargs)
    return wrapper

def ask_about_day(name):
    print("How is your day going, {0}?".format(name))

def comment_about_weather():
    print("It's lovely outside today, isn't it?")

# assign decorator using exec() - possibly unpythonic
function_list = ['ask_about_day', 'comment_about_weather']

for index in range(len(function_list)):
    exec("{0} = my_decorator({0})".format(function_list[index]))

def main():
    name = input("What is your name? ").capitalize()
    if name:
        ask_about_day(name)
    else:
        comment_about_weather()


main()

1 个答案:

答案 0 :(得分:2)

这几乎肯定是一个非常糟糕的主意。

您要做的是按名称替换任意全局变量。正确的方法是调用globals并修改生成的字典。

例如:

g = globals()
for func in function1, function2, function3:
    g[func.__name__] = my_decorator(func)

当然这看起来很丑陋和黑客,但那是因为你正在做的事情本来就是丑陋和黑客,所以Python不会让它看起来很好看,所以你可以假装其他。

另外,请注意然而你这样做,你被迫至少重复一次所有功能的名称。是否真的值得避免重复装饰者的名字相同的次数?这至少和打字一样多,而且更容易犯错误。