首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用可选参数创建装饰器

使用可选参数创建装饰器
EN

Stack Overflow用户
提问于 2010-10-08 14:22:21
回答 10查看 32.2K关注 0票数 74
代码语言:javascript
复制
from functools import wraps

def foo_register(method_name=None):
    """Does stuff."""
    def decorator(method):
        if method_name is None:
            method.gw_method = method.__name__
        else:
            method.gw_method = method_name
        @wraps(method)
        def wrapper(*args, **kwargs):
            method(*args, **kwargs)
        return wrapper
    return decorator

示例:下面的代码使用foo_register来修饰my_function,而不是使用decorator

代码语言:javascript
复制
@foo_register
def my_function():
    print('hi...')

示例:下面的代码按预期工作。

代码语言:javascript
复制
@foo_register('say_hi')
def my_function():
    print('hi...')

如果我想让它在两个应用程序中都能正常工作(一个使用method.__name__,另一个传入名称),我必须在foo_register内部检查第一个参数是否是一个装饰器,如果是的话,我必须这样做:return decorator(method_name) (而不是return decorator)。这种“检查一下它是否是可调用的”看起来非常老土。有没有更好的方法来创建这样的多用途装饰器?

附注:我已经知道我可以要求调用装饰器,但这不是一个“解决方案”。我希望API看起来很自然。我妻子喜欢装饰,我不想破坏这一点。

EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2010-10-08 14:38:25

格伦--我不得不这么做。我想我很高兴没有一个“神奇”的方法来做到这一点。我讨厌这些。

因此,这是我自己的答案(方法名称与上面不同,但概念相同):

代码语言:javascript
复制
from functools import wraps

def register_gw_method(method_or_name):
    """Cool!"""
    def decorator(method):
        if callable(method_or_name):
            method.gw_method = method.__name__
        else:
            method.gw_method = method_or_name
        @wraps(method)
        def wrapper(*args, **kwargs):
            method(*args, **kwargs)
        return wrapper
    if callable(method_or_name):
        return decorator(method_or_name)
    return decorator

示例用法(两个版本的用法相同):

代码语言:javascript
复制
@register_gw_method
def my_function():
    print('hi...')

@register_gw_method('say_hi')
def my_function():
    print('hi...')
票数 28
EN

Stack Overflow用户

发布于 2012-04-24 05:33:50

怎么样

代码语言:javascript
复制
from functools import wraps, partial

def foo_register(method=None, string=None):
    if not callable(method):
        return partial(foo_register, string=method)
    method.gw_method = string or method.__name__
    @wraps(method)
    def wrapper(*args, **kwargs):
        method(*args, **kwargs)
    return wrapper
票数 15
EN

Stack Overflow用户

发布于 2012-04-24 05:59:32

现在,这个旧的线程又回到了顶端,让我只抛出一些Decorator-ception:

代码语言:javascript
复制
def magical_decorator(decorator):
    @wraps(decorator)
    def inner(*args, **kw):
        if len(args) == 1 and not kw and callable(args[0]):
            return decorator()(args[0])
        else:
            return decorator(*args, **kw)
    return inner

现在你神奇的装饰器只有一行之遥了!

代码语言:javascript
复制
@magical_decorator
def foo_register(...):
    # bla bla

顺便说一句,这对任何装饰者都适用。它只会使@foo的行为(尽可能接近)像@foo()一样。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3888158

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档