python - 如何使 @decorator 和 @decorator(args) 共享相同的名称?

标签 python python-3.x python-decorators

我想使用两种类型的装饰器:

一)

@new
def foo():
    print("foo")

b)

@new(arg1, arg2, arg3, ...)
def bar():
    print("bar")

基本上,我想为“新消息”事件创建不同的处理程序。如果您想将其用于所有消息,您应该可以编写 @message.new@message.new(filter) 如果您只希望处理程序覆盖未过滤的处理程序以处理来自某些人员的消息或仅处理带有某些附件的消息。

我的第一个想法是装饰器可以检查它的第一个参数是否是一个函数。如果是,它会猜测它被用作@message.new。如果第一个参数不是函数,它将返回一个装饰器。

from inspect import isfunction

def new(*args):
    x = args[0]
    if isfunction(x):
        return new_noargs(x)
    else:
        return gen_new_args(args)

def new_noargs(func):
    def munc():
        print("new_noargs")
        func()
    return munc 

def gen_new_args(args):
    def dec(func):
        def zunc():
            print("new_args:", args)
            func()
        return zunc
    return dec

它有效:

@new
def foo():
    print("foo")

@new(1,2,3)
def bar():
    print("bar")

不过,它看起来非常笨拙且不符合Python风格。有更方便的方法来解决我的问题吗?另外,如果我想使用 @new(some_function),当前的 new 方法将决定它的调用方式如下:

@new
def some_function():
    ...

如何改进我的代码?

解决方法

@overengineer 是一个装饰器,允许在不使用括号的情况下调用另一个装饰器。它仍然太复杂,但更可重用。

def overengineer(decorator):
    def dec(*args):
        x = args[0]
        if isfunction(x):
            return decorator()(x)
        else:
            return decorator(*args)
    return dec

@overengineer
def new(*args):
    def dec(func):
        def zunc():
            print("args:", args)
            func()
        return zunc
    return dec

最佳答案

我想这个问题的前提是有缺陷的,因为我通过编写 @new() 而不是 @new 并没有损失太多,但我获得了一致性和简单性: new 只是一个装饰器。或者,我可以制作两个不同的装饰器。

关于python - 如何使 @decorator 和 @decorator(args) 共享相同的名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54095208/

相关文章:

python - 我如何在 tkinter 中获取标签的当前宽度

python - 尝试使用 cv2.imshow 时出错

django - 夹层Pagedown嵌入YouTube视频

python - 类定义中的自引用

python - 如何在python 3中正确使用@property装饰器?

python - 将默认装饰器应用于类的所有方法,并有选择地排除它们

python - python bcrypt 出现问题,找不到模块

python - 初始化 float 子类时出错

python - 将 unicode 字符串转换为 float

python - Pandas - 将 12 小时转换为 24 小时(但删除 1900-01-01)