在装饰器中使用self是不好的做法吗?

mic*_*ael 5 python decorator

虽然我知道你不能self直接在装饰器中引用,但我想知道通过拉动它来解决这个问题是不好的做法args[0].我的预感是,但我想确定.

更具体地说,我正在开发一个Web服务的API.大约一半的命令需要传递令牌,稍后可以使用它来撤消它.我想要的是使该标记成为可选参数,如果没有提供,则生成一个.生成令牌需要对服务器进行经过身份验证的调用,该服务器需要来自对象的数据.

虽然我知道我能做到:

def some_command(self, ..., undo_token = None):
    if undo_token = None:
        undo_token = self.get_undo_token()
    ...
    return fnord
Run Code Online (Sandbox Code Playgroud)

我觉得有一种更好的方法,而不是在十几种方法中使用相同的代码.我的想法是写一个装饰者:

@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'])
Run Code Online (Sandbox Code Playgroud)

所以我可以更干净地写

@undoable
def some_command(self, ...):
    ...
    return foo

@undoable
def some_other_command(self, ...):
    ...
    return bar
Run Code Online (Sandbox Code Playgroud)

我是否因为遇到麻烦而陷入困境?

Ale*_*lli 6

我不明白你的编码是什么undoable- 这不是装饰者通常编码的方式,我不知道它@decorator来自哪里(是否还有from youforgottotelluswhence import decorator更邪恶的东西?看看为什么我无法忍受使用的from打造"人工barenames",而不是用漂亮的装饰名字- ?).

使用正常的装饰器编码,例如...:

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
Run Code Online (Sandbox Code Playgroud)

命名包装器的第一个强制性位置参数绝对没有问题self,并且在使用它时可以大大提高清晰度而不是可读性较低args[0].