以编程方式更改 class 对象的文档字符串
Programmatically changing docstring of a class object
我有一个函数和 class 装饰器可以将它们更改为单例,但是文档字符串有点被丢弃了。转换函数 returns 一个 class 对象,它有自己的应该被覆盖的文档字符串。我该如何解决这个问题?
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
文档字符串,而不是函数的文档字符串。
让我们假设原始版本是这样的:
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)
在这种情况下,Bit
是 singleton_function
的 return 值,实际上是 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
类型。我个人喜欢使用 wrapt,因为我可以立即得到我想要的东西。实现该功能并涵盖所有边缘情况需要付出努力,我知道 wrapt 经过了很好的测试并且可以按预期工作。
我有一个函数和 class 装饰器可以将它们更改为单例,但是文档字符串有点被丢弃了。转换函数 returns 一个 class 对象,它有自己的应该被覆盖的文档字符串。我该如何解决这个问题?
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
文档字符串,而不是函数的文档字符串。
让我们假设原始版本是这样的:
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)
在这种情况下,Bit
是 singleton_function
的 return 值,实际上是 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
类型。我个人喜欢使用 wrapt,因为我可以立即得到我想要的东西。实现该功能并涵盖所有边缘情况需要付出努力,我知道 wrapt 经过了很好的测试并且可以按预期工作。