【问题标题】:Method and property aliases with custom docstring in PythonPython中具有自定义文档字符串的方法和属性别名
【发布时间】:2019-06-06 19:58:33
【问题描述】:

我已经实现了以下装饰器:

class alias(object):

    """
    A decorator for implementing method aliases.
    """

    def __init__(self, *aliases):

        self.aliases = set(aliases)

    def __call__(self, obj):

        if type(obj) == property:
            obj.fget._aliases = self.aliases
        else:
            obj._aliases = self.aliases

        return obj

def aliased(aliased_class):

    """
    A decorator for enabling method aliases.
    """

    aliased_class_dict = aliased_class.__dict__.copy()
    aliased_class_set = set(aliased_class_dict)

    for name, method in aliased_class_dict.items():

        aliases = None

        if (type(method) == property) and hasattr(method.fget, '_aliases'):
            aliases = method.fget._aliases
        elif hasattr(method, '_aliases'):
            aliases = method._aliases

        if aliases:

            for a in aliases - aliased_class_set:
                setattr(aliased_class, a, method)

    return aliased_class

下面是我如何使用它们来创建属性和方法的可调用别名的示例:

@aliased
class MyClass(object):

    @alias('a')
    @property
    def alpha(self) -> float:

        """
        Returns the value of alpha.
        """

        return 2.5

    @alias('agt')
    def alpha_greater_than(value) -> bool:

        """
        Checks whether alpha is greater than the given value.
        """

        return self.alpha > value

mc = MyClass()
result = mc.agt(3.0)
# ...

现在我正在打包我的项目并构建文档。目前,别名方法和属性“继承”原始实体的相同文档字符串。我想知道是否可以在装饰器级别操作别名实体的文档字符串,使它们看起来像:

此方法/属性是 X 的别名。

【问题讨论】:

    标签: python python-3.x decorator alias docstring


    【解决方案1】:

    你可以直接操作X.__doc__如:

    if aliases:
    
        for a in aliases - aliased_class_set:
            method.__doc__ = "This function is an alias of %s." % a
            setattr(aliased_class, a, method)
    

    但问题是原来的引用X也会受到影响。所以你最好使用包装器:

    def aliased(aliased_class):
    
        """
        A decorator for enabling method aliases.
        """
        def wrapper(func):
            @functools.wraps(func)
            def inner(*args, **kwargs):
                return func(*args, **kwargs)
            return inner
    
        aliased_class_dict = aliased_class.__dict__.copy()
        aliased_class_set = set(aliased_class_dict)
    
        for name, method in aliased_class_dict.items():
    
            aliases = None
    
            if (type(method) == property) and hasattr(method.fget, '_aliases'):
                aliases = method.fget._aliases
            elif hasattr(method, '_aliases'):
                aliases = method._aliases
    
            if aliases:
    
                for a in aliases - aliased_class_set:
                    wrapped_method = wrapper(method)
                    wrapped_method.__doc__ = "This function is an alias of %s." % a
                    setattr(aliased_class, a, wrapped_method)
    
        return aliased_class
    

    并测试:

    print(mc.alpha_greater_than.__doc__)
    print(mc.agt.__doc__)
    

    输出:

            Checks whether alpha is greater than the given value.
    
    This function is an alias of agt.
    

    【讨论】:

    • 这就像一个魅力,除了别名实体在 Sphinx 文档中丢失了它们的签名蚂蚁类型提示这一事实。例如,“agt(value) -> bool”变成了“agt(**kwargs)”。有什么办法保存吗?
    • 好吧,我没有测试它,但我相信有。我将修改我的答案以使用functools.wraps
    • @TommasoBelluzzo 我已经检查过functools.wraps 工作正常 :) 查看我的更新。
    猜你喜欢
    • 1970-01-01
    • 2015-01-19
    • 2016-03-06
    • 1970-01-01
    • 1970-01-01
    • 2019-05-08
    • 2013-04-10
    • 1970-01-01
    • 2018-07-30
    相关资源
    最近更新 更多