Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.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装饰器_Python_Decorator - Fatal编程技术网

使用带括号或不带括号的python装饰器

使用带括号或不带括号的python装饰器,python,decorator,Python,Decorator,在Python中,使用带括号和不带括号的同一个修饰符有什么区别 例如: 不带括号: @some_decorator def some_method(): pass @some_decorator() def some_method(): pass 带括号: @some_decorator def some_method(): pass @some_decorator() def some_method(): pass some_decorator在第一个代

在Python中,使用带括号和不带括号的同一个修饰符有什么区别

例如:

不带括号:

@some_decorator
def some_method():
    pass
@some_decorator()
def some_method():
    pass
带括号:

@some_decorator
def some_method():
    pass
@some_decorator()
def some_method():
    pass

some_decorator
在第一个代码段中是一个常规的decorator:

@some_decorator
def some_method():
    pass
@some_decorator()
def some_method():
    pass
def some_decorator(arg=None):
    def decorator(func):
        def wrapper(*a, **ka):
            return func(*a, **ka)
        return wrapper

    if callable(arg):
        return decorator(arg) # return 'wrapper'
    else:
        return decorator # ... or 'decorator'
def someDecorator(arg=None):
    def decorator(func):
        def wrapper(*a, **ka):
            if not callable(arg):
                print (arg)
                return func(*a, **ka)
            else:
                return 'xxxxx'
        return wrapper

    if callable(arg):
        return decorator(arg) # return 'wrapper'
    else:
        return decorator # ... or 'decorator'

@someDecorator(arg=1)
def my_func():
    print('aaa')

@someDecorator
def my_func1():
    print('bbb')

if __name__ == "__main__":
    my_func()
    my_func1()
相当于

some_method = some_decorator(some_method)
另一方面,第二个代码段中的some_decorator是返回decorator的可调用函数:

@some_decorator
def some_method():
    pass
@some_decorator()
def some_method():
    pass
def some_decorator(arg=None):
    def decorator(func):
        def wrapper(*a, **ka):
            return func(*a, **ka)
        return wrapper

    if callable(arg):
        return decorator(arg) # return 'wrapper'
    else:
        return decorator # ... or 'decorator'
def someDecorator(arg=None):
    def decorator(func):
        def wrapper(*a, **ka):
            if not callable(arg):
                print (arg)
                return func(*a, **ka)
            else:
                return 'xxxxx'
        return wrapper

    if callable(arg):
        return decorator(arg) # return 'wrapper'
    else:
        return decorator # ... or 'decorator'

@someDecorator(arg=1)
def my_func():
    print('aaa')

@someDecorator
def my_func1():
    print('bbb')

if __name__ == "__main__":
    my_func()
    my_func1()
相当于

some_method = some_decorator()(some_method)
正如邓肯在评论中指出的,一些装饰师被设计成双向工作。下面是这种装饰器的一个非常基本的实现:

@some_decorator
def some_method():
    pass
@some_decorator()
def some_method():
    pass
def some_decorator(arg=None):
    def decorator(func):
        def wrapper(*a, **ka):
            return func(*a, **ka)
        return wrapper

    if callable(arg):
        return decorator(arg) # return 'wrapper'
    else:
        return decorator # ... or 'decorator'
def someDecorator(arg=None):
    def decorator(func):
        def wrapper(*a, **ka):
            if not callable(arg):
                print (arg)
                return func(*a, **ka)
            else:
                return 'xxxxx'
        return wrapper

    if callable(arg):
        return decorator(arg) # return 'wrapper'
    else:
        return decorator # ... or 'decorator'

@someDecorator(arg=1)
def my_func():
    print('aaa')

@someDecorator
def my_func1():
    print('bbb')

if __name__ == "__main__":
    my_func()
    my_func1()

是一个更复杂的示例。

使用arg inside decorator的一些实际工作代码:

@some_decorator
def some_method():
    pass
@some_decorator()
def some_method():
    pass
def some_decorator(arg=None):
    def decorator(func):
        def wrapper(*a, **ka):
            return func(*a, **ka)
        return wrapper

    if callable(arg):
        return decorator(arg) # return 'wrapper'
    else:
        return decorator # ... or 'decorator'
def someDecorator(arg=None):
    def decorator(func):
        def wrapper(*a, **ka):
            if not callable(arg):
                print (arg)
                return func(*a, **ka)
            else:
                return 'xxxxx'
        return wrapper

    if callable(arg):
        return decorator(arg) # return 'wrapper'
    else:
        return decorator # ... or 'decorator'

@someDecorator(arg=1)
def my_func():
    print('aaa')

@someDecorator
def my_func1():
    print('bbb')

if __name__ == "__main__":
    my_func()
    my_func1()
输出为:

1
aaa

简而言之,修饰符允许向函数组和类组添加丰富的特性,而无需对其进行任何修改

理解
@some_decorator
@some_decorator()
之间区别的关键在于前者是decorator,而后者是返回decorator的函数(或可调用的函数)

我认为,看到每个案例的实施有助于理解差异:

@some_decorator
应用程序:

@some_decorator
def some_method():
    pass
some_method = some_decorator(some_method)
@some_decorator()
def some_method():
    pass
some_method = some_decorator()(some_method)
@some_decorator('hello', 'bye')
def some_method():
    pass
some_method = some_decorator('hello', 'bye')(some_method)
等效性:

@some_decorator
def some_method():
    pass
some_method = some_decorator(some_method)
@some_decorator()
def some_method():
    pass
some_method = some_decorator()(some_method)
@some_decorator('hello', 'bye')
def some_method():
    pass
some_method = some_decorator('hello', 'bye')(some_method)
@some\u decorator()
应用程序:

@some_decorator
def some_method():
    pass
some_method = some_decorator(some_method)
@some_decorator()
def some_method():
    pass
some_method = some_decorator()(some_method)
@some_decorator('hello', 'bye')
def some_method():
    pass
some_method = some_decorator('hello', 'bye')(some_method)
等效性:

@some_decorator
def some_method():
    pass
some_method = some_decorator(some_method)
@some_decorator()
def some_method():
    pass
some_method = some_decorator()(some_method)
@some_decorator('hello', 'bye')
def some_method():
    pass
some_method = some_decorator('hello', 'bye')(some_method)
注意,现在更容易看到
@some\u decorator()
是一个返回decorator的函数,而
some\u decorator
只是一个decorator。请记住,有些装饰师是双向工作的

所以现在你可能想知道为什么我们有这两种情况,而前一个版本似乎更简单。答案是,如果您想将参数传递给装饰器,使用
@some\u decorator()
将允许您这样做。让我们看看一些正在运行的代码:

def some_decorator(arg1, arg2):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(arg1)
            print(arg2)
            return func(*args, **kwargs)
        return wrapper
    return decorator
应用程序:

@some_decorator
def some_method():
    pass
some_method = some_decorator(some_method)
@some_decorator()
def some_method():
    pass
some_method = some_decorator()(some_method)
@some_decorator('hello', 'bye')
def some_method():
    pass
some_method = some_decorator('hello', 'bye')(some_method)
等效性:

@some_decorator
def some_method():
    pass
some_method = some_decorator(some_method)
@some_decorator()
def some_method():
    pass
some_method = some_decorator()(some_method)
@some_decorator('hello', 'bye')
def some_method():
    pass
some_method = some_decorator('hello', 'bye')(some_method)

注意:我认为值得一提的是,装饰器可以作为函数或类实现。查看更多信息。

如果您有一个可以使用参数或不使用参数的装饰器,您可以在装饰器上使用以下装饰器,使其可以使用括号或不使用括号,如下所示:

>@ommittable\u括号(allow\u partial=True)
... def乘数(乘以=2):
...     def装饰器(func):
...         def乘_包装(*args,**kwargs):
...             返回乘以*func(*args,**kwargs)
...         返回乘法包装器
...     返回装饰器
...
>>>@乘数
... def无括号():
...     返回2
...
>>>无括号()
4.
>>>@multiplier()
... def括号():
...     返回2
...
>>>括号()
4.
>>>@乘数(3)
... def参数():
...     返回2
...
>>>参数()
6.
如果给定了
allow\u partial=True
,则生成的装饰程序也将使用
partial

>>从functools导入部分
>>>乘以3=部分(乘数,乘以3)
>>>
>>>@乘以3
... def partial_no_括号():
...     返回2
...
>>>部分括号()
6.
>>>@乘以3()
... def部分括号()
...     返回2
...
>>>部分括号()
6.
装饰代码:

从functools导入包装
def省略表的括号(可能是decorator=None,/,allow\u partial=False):
“”“允许在没有括号的情况下使用装饰器的装饰器”“”
def装饰器(func):
@包装(装饰)
def包装(*args,**kwargs):
如果len(args)==1且可调用(args[0]):
如果允许_部分:
返回函数(**kwargs)(参数[0])
elif not kwargs:
return func()(参数[0])
返回函数(*args,**kwargs)
返回包装器
如果您的decorator没有:
返回装饰器
其他:
返回装饰器(可能是装饰器)

作为奖励,这个decorator decorator本身可以使用括号,也可以不使用括号

这些不是大括号,而是圆括号。大括号是
{}
@DanielRoseman很好的提示,经常在寻找正确的单词时苦苦挣扎……下面是一个很好的答案。值得指出的是,这一区别与
foo
foo()
之间的区别是一样的,包括不在装饰器中。值得补充的是,有些装饰器是双向工作的,例如
@pytest。fixture
可以直接用作装饰器,或者使用一些命名参数调用,在这种情况下它返回一个装饰器。可调用装饰器的意义是什么?在AICT中,
someDecorator()
将始终返回相同的内容,因为它不接受任何参数(除非
someDecorator
持有状态)。所以我假设可调用的装饰器持有一个状态?还要注意,Duncan提到的技巧现在可以完全自动化,多亏了。顺便说一句,我是作者:)这是一个非常好的技巧,但它并没有真正回答最初的问题,即使用括号与不使用括号有什么区别。