简体   繁体   English

Python 装饰 class 文档

[英]Python decorated class documentation

I'm using a decorator for singletons in python, implemented as shown below.我在 python 中使用单例装饰器,实现如下所示。

I'd like to have the pydoc of the decorated class being exactly the same as the pydoc of the non decorated class, but I don't find how:我想让装饰的 class 的 pydoc 与未装饰的 class 的 pydoc 完全相同,但我不知道如何:

  • Without the getSingletonInstance.__doc__ = cls.__doc__ line, the pydoc of the decorated class gives the pydoc of the singleton function.如果没有getSingletonInstance.__doc__ = cls.__doc__行,装饰的 class 的 pydoc 会给出singleton ZC1C425268E68385D1AB5074C17A9 的 pydoc。

  • With the getSingletonInstance.__doc__ = cls.__doc__ line, the pydoc of the decorated class gives only the "top level" docstring.使用getSingletonInstance.__doc__ = cls.__doc__行,装饰的 class 的 pydoc 仅给出“顶级”文档字符串。

How can I proceed?我该如何进行?

Thanks.谢谢。

def singleton(cls):
    """A singleton decorator

    Warnings
    --------
    Singleton gdecorated calsses cannot be inhehited

    Example
    -------
    >>> from decorators import singleton
    >>> @singleton
    ... class SingletonDemo():
    ...     pass
    >>> d1 = SingletonDemo()
    >>> d1.a = 0xCAFE
    >>> d2 = SingletonDemo()
    >>> id(d1) == id(d2)
    True
    >>> d1 == d2
    True
    >>> d2.a == 0xCAFE
    True

    References
    ----------
    See case 2 of https://www.python.org/dev/peps/pep-0318/#examples
    """
    _instances = {}

    def getSingletonInstance():
        if cls not in _instances:
            _instances[cls] = cls()
        return _instances[cls]

    getSingletonInstance.__doc__ = cls.__doc__

    return getSingletonInstance

Try using functools.wraps :尝试使用functools.wraps

import functools

def wrapper(cls):
    _instances = {}
    class inner(cls):
        def __new__(subcls):
            if subcls not in _instances:
                _instances[subcls] = object.__new__(subcls)
            return _instances[subcls]
    inner.__doc__=cls.__doc__
    return inner

@wrapper
class A(object):
    """Example Docstring"""
    def method(self):
        """Method Docstring"

A.__doc__
# "Example Docstring"
A.method.__doc__
# "Method Docstring"

Answer summarizing all the discussions, with example.回答总结所有讨论,并举例说明。 Thanks a lot to everybody.非常感谢大家。

This solution:这个解决方案:

  • Preserves the docstring保留文档字符串
  • Preserves the type保存类型
  • Supports static and class methods支持 static 和 class 方法

Limitations:限制:

  • Singletons cannot be inherited, which is meaningful regarding to the context单例不能被继承,这对于上下文是有意义的

Solution: def singleton(cls):解决方案:def 单例(cls):

    """A singleton decorator

    Warnings
    --------
    Singleton decorated classes cannot be inhehited

    Example
    -------
    >>> import abc
    >>> 
    >>> @singleton
    ... class A():
    ...     "Ad-hoc documentation of class A"
    ...     def __init__(self):
    ...         "Ad-hoc documentation of class A constructor"
    ...         print("constructor called")
    ...         self.x = None
    ...     @classmethod
    ...     def cm(cls):
    ...         "a class method"
    ...         print("class method called")
    ...     def im(self):
    ...         "an instance method"
    ...         print("instance method called")
    ...     @staticmethod
    ...     def sm():
    ...         "a static method"
    ...         print("static method called")
    ... 
    >>> @singleton
    ... class P(abc.ABCMeta):
    ...     @abc.abstractmethod
    ...     def __init__(self):
    ...         pass
    ... 
    >>> class C(P):
    ...     def __init__(self):
    ...         print("C1 constructor called")
    ... 
    >>> a1 = A()
    constructor called
    >>> a1.x = 0xCAFE
    >>> a1.x
    51966
    >>> a2 = A()
    >>> a2.x
    51966
    >>> a1.x == a2.x
    True
    >>> a1 == a2
    True
    >>> id(a1) == id(a2)
    True
    >>> type(a1) == type(a2)
    True
    >>> isinstance(a1, A)
    True
    >>> ta1 = type(a1)
    >>> issubclass(ta1, A)
    True
    >>> A.cm()
    class method called
    >>> a1.cm()
    class method called
    >>> A.sm()
    static method called
    >>> a1.sm()
    static method called
    >>> a1.im()
    instance method called
    >>> try:
    ...     C()
    ... except Exception as e:
    ...     type(e)
    ... 
    <class 'TypeError'>

    """
    _instances = {}
    _constructorCalled = []
    class inner(cls):
        def __new__(subcls):
            if subcls not in _instances:
                _instances[subcls] = cls.__new__(subcls)
            return _instances[subcls]
        def __init__(self):
            if type(self) not in _constructorCalled:
                cls.__init__(self)
                _constructorCalled.append(type(self))
        __init__.__doc__ = cls.__init__.__doc__
        __new__.__doc__ = cls.__new__.__doc__
        if __new__.__doc__ == (
            "Create and return a new object.  "
            "See help(type) for accurate signature."
        ):
            __new__.__doc__ = "Returns a singleton instance"
    inner.__doc__ = cls.__doc__
    return inner

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM