New*_*Guy 3 python decorator python-decorators
我正在尝试在工作中集成一个非常旧的系统和一个更新的系统.我能做的最好的事情就是利用系统使用的RSS消防站类型的饲料.目标是使用此RSS源使其他系统在某些人执行操作时执行某些操作.
我的想法是围绕某些函数包装装饰器,以检查用户(RSS提要中提供的用户ID)是否在新系统中具有权限.
我当前的解决方案有很多看起来像这样的函数,它们基于actionfeed中的字段调用:
actions_dict = {
...
'action1': function1
}
actions_dict[RSSFEED['action_taken']](RSSFEED['user_id'])
def function1(user_id):
if has_permissions(user_id):
# Do this function
Run Code Online (Sandbox Code Playgroud)
我想创建一个has_permissions装饰器,user_id以便我可以删除has_permissions每个函数中的冗余检查.
@has_permissions(user_id)
def function1():
# Do this function
Run Code Online (Sandbox Code Playgroud)
不幸的是,我不知道如何编写这样的装饰器.我看到的所有教程都有一个@has_permissions()带有硬编码值的行,但在我的情况下,它需要在运行时传递,并且每次调用函数时都会有所不同.
我该如何实现此功能?
在你的问题中,你已经命名了两个,检查了user_id,以及想要的装饰器has_permissions,所以我将使用一个名称更清晰的例子:让我们做一个装饰器,当调用底层(装饰)函数时颜色(一个字符串)是'green'.
装饰器本身(if_green在我下面的例子中)是一个函数.它需要一个函数作为参数进行修饰(function在我的示例中命名)并返回一个函数(run_function_if_green在示例中).通常,返回的函数在某个时刻调用传递的函数,从而使用它可能在其之前或之后运行的其他操作来"装饰"它,或者两者兼而有之.
当然,它可能只是有条件地运行它,因为你似乎需要:
def if_green(function):
def run_function_if_green(color, *args, **kwargs):
if color == 'green':
return function(*args, **kwargs)
return run_function_if_green
@if_green
def print_if_green():
print('what a nice color!')
print_if_green('red') # nothing happens
print_if_green('green') # => what a nice color!
Run Code Online (Sandbox Code Playgroud)
当你用装饰器装饰一个函数时(正如我在print_if_green这里所做的那样)会发生装饰器(if_green我的例子中的函数工厂)被原始函数调用(print_if_green正如你在上面的代码中看到的那样).就其本质而言,它返回不同的功能.然后Python 将原始函数替换为装饰器返回的函数.
因此,在后续调用中,返回的函数(run_function_if_green原始的print_if_greenas function)被调用,print_if_green并且有条件地调用该原始函数print_if_green.
对decorator(if_green)的调用仅对每个修饰函数发生一次,而不是每次调用修饰函数时都会发生.但是,当装饰器返回的函数一次性永久替换原始函数时,每次调用原始函数时都会调用它而不是原始函数.如果我们允许的话,它可以采取论据.
我给它一个参数color,它用它来决定是否调用修饰函数.此外,我已经给它了惯用的vararg参数,它用来调用包装函数(如果它调用它),这样我就可以使用任意数量的位置和关键字参数来修饰函数:
@if_green
def exclaim_if_green(exclamation):
print(exclamation, 'that IS a nice color!')
exclaim_if_green('red', 'Yay') # again, nothing
exclaim_if_green('green', 'Wow') # => Wow that IS a nice color!
Run Code Online (Sandbox Code Playgroud)
装饰函数的结果if_green是新的第一个参数被添加到其签名之前,该签名对于原始函数是不可见的(因为run_function_if_green它不转发它).由于您可以自由地实现装饰器返回的函数,它还可以使用更少,更多或不同的参数调用原始函数,在将它们传递给原始函数之前对它们执行任何所需的转换,或者执行其他疯狂的操作.
理解装饰器需要了解和理解Python语言的各种其他概念.(其中大多数并非特定于Python,但人们可能仍然不了解它们.)
为了简洁起见(这个答案足够长),我已经跳过或掩盖了大部分内容.有关更全面的快速运行(我认为)所有相关的快速运行,请参阅12个简单步骤中的了解Python装饰器!.
| 归档时间: |
|
| 查看次数: |
3084 次 |
| 最近记录: |