Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在装饰师中使用self是一种不好的做法吗?_Python_Decorator - Fatal编程技术网

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
,所以我(错误地)认为这是最佳实践。