2016-09-17 31 views
3

我有一個函數和類裝飾器,它們將它們更改爲單例,但文檔類型是丟棄的。轉換函數返回一個具有自己的文檔字符串的類對象,該文檔字符串應該被覆蓋。我該如何解決這個問題?編程方式更改類對象的文檔字符串

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) 

檢查Bit產生了BitInteger文檔字符串,而不是函數的一個。

回答

1

讓我們假設原來的版本是這樣的:

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__) 

與Python3.5運行這給輸出:

b.__doc_ : BitsInteger docstring 

這可能不是你所期望的。當我們與python -i original.py運行,我們可以看看究竟怎麼回事就在這裏:

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

正如你可以看到b實際類型爲BitsInteger

的原因是什麼回事的是,當你寫:

@singleton_function 
def Bit(): 
    """Bit docstring""" 
    ... 
    return BitsInteger(1) 

你真的剛開語法糖這樣的:

def Bit(): 
    """Bit docstring""" 
    ... 
    return BitsInteger(1) 
Bit = singleton_function(Bit) 

在這種情況下,Bitsingleton_function的返回值,它實際上是BitsInteger。我發現,當你消除語法糖時,它會更清晰地發生在這裏。

如果你想有一個裝飾的方便,不改變文檔字符串我推薦使用wrapt

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__) 

此輸出:

b.__doc_ : A 1-bit BitField; must be enclosed in a BitStruct 

現在,當你在看Vars()您會看到'b': <FunctionWrapper at 0x7f9a9ac42ba8 for function at 0x7f9a9a9e8c80>不再是BitInteger類型。我個人喜歡使用包裝,因爲我立即得到我想要的東西。實現該功能並覆蓋所有邊緣案例需要付出努力,而且我知道包裝已經過良好測試並按預期工作。

+0

本質上'位= BitInteger(1)'。你在位定義中有一個錯字,它不會返回一個類,而是一個實例。更糟糕的是,它似乎不適用於PY3,它不會繼承/ >>操作符。 – ArekBulski

+0

我用cPython 3.5運行了這個。如果您可以將「BitsInteger」類的一些定義與您在問題中需要實現的內容相結合,可能會幫助我在這裏改進答案。我不完全清楚你想解決的原始問題是什麼。你是否需要'Bit'來調用並始終返回相同的(單例)對象? – shuttle87

+0

位應該是一個類實例,它具有從函數而不是類獲取的文檔字符串。而已。我接受你的解決方案,即使它有時可以工作。 – ArekBulski