Python 在装饰师中使用self是一种不好的做法吗?
虽然我知道不能在装饰器中直接引用Python 在装饰师中使用self是一种不好的做法吗?,python,decorator,Python,Decorator,虽然我知道不能在装饰器中直接引用self,但我想知道从args[0]中提取它是否是一种不好的做法。我的直觉是确实如此,但我想确定 更具体地说,我正在开发web服务的API。大约有一半的命令需要传递一个令牌,该令牌可以在以后用于撤消它。我想要的是使该令牌成为可选参数,如果没有提供,则生成一个。生成令牌需要对服务器进行身份验证调用,而服务器需要来自对象的数据 虽然我知道我能做到: def some_command(self, ..., undo_token = None): if undo_
self
,但我想知道从args[0]
中提取它是否是一种不好的做法。我的直觉是确实如此,但我想确定
更具体地说,我正在开发web服务的API。大约有一半的命令需要传递一个令牌,该令牌可以在以后用于撤消它。我想要的是使该令牌成为可选参数,如果没有提供,则生成一个。生成令牌需要对服务器进行身份验证调用,而服务器需要来自对象的数据
虽然我知道我能做到:
def some_command(self, ..., undo_token = None):
if undo_token = None:
undo_token = self.get_undo_token()
...
return fnord
我觉得有比在十几个方法中使用相同的代码更好的方法。我的想法是写一个装饰师:
@decorator
def undoable(fn, *args, **kwargs):
if 'undo_token' not in kwargs:
kwargs['undo_token'] = args[0].get_undo_token()
return (fn(*args, **kwargs), kwargs['undo_token'])
这样我才能写得更清楚
@undoable
def some_command(self, ...):
...
return foo
@undoable
def some_other_command(self, ...):
...
return bar
我是在自找麻烦吗?装饰程序以一种通用的方式扩展它所装饰的函数的功能。如果装饰者不想对函数或它的args或kwargs做任何假设,那么它是最通用的形式,可以很容易地与许多函数一起使用 然而,如果您想对传递到函数上的内容做些什么,这应该没问题,但它们的适用性是有限的,如果您在decorator中使用的底层细节发生更改,它们可能会中断 在上面的decorator中,如果对象删除了方法get\u undo\u token(),您也需要重新访问decorator。这样做很好,但要记录约束,还要将文档添加到方法doc-It-self中
只有在绝对必要时才这样做。它可以创建更多的通用装饰器 我不明白你在为什么编写
可撤销的
——这不是装饰程序通常的编码方式,我也不知道@decorator
是从哪里来的(你忘了有的吗?
从哪里导入装饰程序
或者更邪恶的东西?看看为什么我不能忍受使用的来构建“人造裸名”,而不是使用漂亮的装饰的名称?-)
使用正常的装饰器编码,例如…:
import functools
def undoable(f):
@functools.wraps(f)
def wrapper(self, *a, **k):
tok = k.get('undo_token')
if tok is None:
tok = k['undo_token'] = self.get_undo_token()
return f(self, *a, **k), tok
return wrapper
命名包装器的第一个强制性位置参数self
,绝对没有问题,使用它比使用装饰器模式实现“撤销”的可读性较差的args[0]+1更清晰。“装饰者对被装饰的函数的参数有要求没有错;只需确保它是有文档记录的。+1“我无法忍受使用来自
的来构建‘人工裸名’”是的,来自decorator import decorator的确实让Q的代码无法理解,因为没有一个“参考URL”,就像“人工裸名”通常所做的那样——可惜Michele选择在他的文档中使用它,给用户一个如此可怕的例子。更遗憾的是,至少在这个用例中,第三方装饰器模块将参数混在一起,使得代码很难理解,而简单的Python语法将“被装饰的函数”与“包装器的参数”巧妙地分开——我宁愿失去“签名保留”的黑魔法而不是把代码弄得乱七八糟。谢谢。我看到这里使用了很多@decorator
,所以我(错误地)认为这是最佳实践。