Programatically changing docstring of a class object
<p>I have a function and class decorator that changes them to singletons but the docstrings are kind of dropped. Transforming function returns a class object that has its own docstring which should be overwritten. How can I work around this?</p>

<pre><code>def singleton(cls):
    return cls()

def singletonfunction(func):
    return func()

@singletonfunction
def Bit():
    """A 1-bit BitField; must be enclosed in a BitStruct"""
    return BitsInteger(1)
</code></pre>

<p>Inspecting <code>Bit</code> yields the <code>BitInteger</code> docstring, not the function's one.</p>

<p>Lets assume the original version is something like this:</p>

<pre><code>class BitsInteger:
    """BitsInteger docstring"""
    def __init__(self, num):
        pass

def singleton(cls):
    return cls()

def singletonfunction(func):
    return func()

@singletonfunction
def Bit():
    """A 1-bit BitField; must be enclosed in a BitStruct"""
    return BitsInteger(1)

b = Bit
print("b.__doc__ :", b.__doc__)
</code></pre>

<p>Running this with Python3.5 gives the output:</p>

<pre><code>b.__doc_ : BitsInteger docstring
</code></pre>

<p>This might not be what you expect. When we run with <code>python -i original.py</code> we can have a look around at what is really going on here:</p>

<pre><code>&gt;&gt;&gt; vars()
{'__name__': '__main__', '__builtins__': &lt;module 'builtins' (built-in)&gt;, 'b': &lt;__main__.BitsInteger object at 0x7ff05d2ae3c8&gt;, '__spec__': None, 'singletonfunction': &lt;function singletonfunction at 0x7ff05d2b40d0&gt;, 'singleton': &lt;function singleton at 0x7ff05d30cd08&gt;, '__cached__': None, 'BitsInteger': &lt;class '__main__.BitsInteger'&gt;, '__loader__': &lt;_frozen_importlib.SourceFileLoader object at 0x7ff05d2eb4a8&gt;, '__package__': None, 'Bit': &lt;__main__.BitsInteger object at 0x7ff05d2ae3c8&gt;, '__doc__': None}
&gt;&gt;&gt; 
</code></pre>

<p>As you can see <code>b</code> is actually of type <code>BitsInteger</code></p>

<p>The reason is because what's really going on is that when you write:</p>

<pre><code>@singleton_function
def Bit():
    """Bit docstring"""
    ...
    return BitsInteger(1)
</code></pre>

<p>You are really just getting syntactic sugar for this:</p>

<pre><code>def Bit():
    """Bit docstring"""
    ...
    return BitsInteger(1)
Bit = singleton_function(Bit)
</code></pre>

<p>In this case <code>Bit</code> is the return value of <code>singleton_function</code> which is actually a <code>BitsInteger</code>. I find when you strip back the syntactic sugar it's much clearer what's going on here.</p>

<p>If you would like to have the convenience of a decorator that doesn't change the docstring I'd recommend using <a href="https://pypi.python.org/pypi/wrapt" rel="nofollow">wrapt</a></p>

<pre><code>import wrapt

class BitsInteger:
    """BitsInteger docstring"""
    def __init__(self, num):
        pass

def singleton(cls):
    return cls()

@wrapt.decorator
def singletonfunction(func):
    return func()

@singletonfunction
def Bit():
    """A 1-bit BitField; must be enclosed in a BitStruct"""
    return BitsInteger(1)

b = Bit
print("b.__doc_ :", b.__doc__)
</code></pre>

<p>This outputs:</p>

<pre><code>b.__doc_ : A 1-bit BitField; must be enclosed in a BitStruct
</code></pre>

<p>Now when you look at <code>Vars()</code> you see that <code>'b': &lt;FunctionWrapper at 0x7f9a9ac42ba8 for function at 0x7f9a9a9e8c80&gt;</code> which is no longer a <code>BitInteger</code> type. Personally I like using wrapt because I get what I want immediately. Implementing that functionality and covering all the edge cases takes effort and I know that wrapt is well tested and works as intended.</p>

python decorator python-decorators docstring