Python 将docstring添加到namedtuples?
是否可以简单地将文档字符串添加到namedtuple 我试过了Python 将docstring添加到namedtuples?,python,docstring,namedtuple,Python,Docstring,Namedtuple,是否可以简单地将文档字符串添加到namedtuple 我试过了 from collections import namedtuple Point = namedtuple("Point", ["x", "y"]) """ A point in 2D space """ # Yet another test """ A(nother) point in 2D space """ Point2 = namedtuple("Point2", ["x", "y"]) print Point.__
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
"""
A point in 2D space
"""
# Yet another test
"""
A(nother) point in 2D space
"""
Point2 = namedtuple("Point2", ["x", "y"])
print Point.__doc__ # -> "Point(x, y)"
print Point2.__doc__ # -> "Point2(x, y)"
但这并不能解决问题。是否可以通过其他方式执行此操作?否,您只能将文档字符串添加到模块、类和函数(包括方法)您可以通过围绕
namedtuple
的返回值创建一个简单的空包装类来实现此目的。我创建的文件的内容(nt.py
):
然后在Python REPL中:
>>> print nt.Point.__doc__
A point in 2d space
或者你可以:
>>> help(nt.Point) # which outputs...
哪些产出:
A point in 3d space
您可以编造自己版本的Raymond Hettinger的,并添加一个可选的
docstring
参数。但是,使用与配方中相同的基本技术定义自己的工厂函数会更容易,也可以说更好。无论哪种方式,您最终都会得到一些可重用的东西
from collections import namedtuple
def my_namedtuple(typename, field_names, verbose=False,
rename=False, docstring=''):
'''Returns a new subclass of namedtuple with the supplied
docstring appended to the default one.
>>> Point = my_namedtuple('Point', 'x, y', docstring='A point in 2D space')
>>> print Point.__doc__
Point(x, y): A point in 2D space
'''
# create a base class and concatenate its docstring and the one passed
_base = namedtuple(typename, field_names, verbose, rename)
_docstring = ''.join([_base.__doc__, ': ', docstring])
# fill in template to create a no-op subclass with the combined docstring
template = '''class subclass(_base):
%(_docstring)r
pass\n''' % locals()
# execute code string in a temporary namespace
namespace = dict(_base=_base, _docstring=_docstring)
try:
exec template in namespace
except SyntaxError, e:
raise SyntaxError(e.message + ':\n' + template)
return namespace['subclass'] # subclass object created
在谷歌遇到这个老问题的时候,我也在想同样的事情 我只是想指出,通过从类声明中调用namedtuple(),您可以进一步整理它:
from collections import namedtuple
class Point(namedtuple('Point', 'x y')):
"""Here is the docstring."""
在Python3中,不需要包装器,因为类型的
\uuu doc\uu
属性是可写的
from collections import namedtuple
Point = namedtuple('Point', 'x y')
Point.__doc__ = '''\
A 2-dimensional coordinate
x - the abscissa
y - the ordinate'''
这与标准类定义密切相关,其中docstring紧跟在标题之后
class Point():
'''A 2-dimensional coordinate
x - the abscissa
y - the ordinate'''
<class code>
class Point():
''二维坐标
横坐标
y-纵坐标''
这在Python2中不起作用
AttributeError:“type”对象的属性“\uuuu doc\uuuuuuuuuuuuuuuuuuuuuuuuuuuuu”不可写
无需按照公认答案的建议使用包装器类。简单地按字面意思添加文档字符串:
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
Point.__doc__="A point in 2D space"
这导致:(使用ipython3
的示例):
[1]中的:点?
类型:类型
字符串形式:
文档字符串:二维空间中的点
在[2]中:
瞧
是否可以简单地将文档字符串添加到namedtuple?
是的,在几个方面
子类typing.NamedTuple-Python 3.6+
从Python 3.6开始,我们可以直接使用类定义和类型.NamedTuple
以及docstring(和注释!):
输入import NamedTuple
课程卡(名称为双):
“”“这是一种卡片类型。”“”
西装:str
排名:str
与Python2相比,没有必要声明空的\uuuuuuuuuuuuuuuuuuuu
。在Python3.8中,即使是子类也不需要它
请注意,声明\uuuuu插槽\uuuuu
不能为非空
在Python3中,您还可以轻松地在namedtuple上更改文档:
NT = collections.namedtuple('NT', 'foo bar')
NT.__doc__ = """:param str foo: foo name
:param list bar: List of bars to bar"""
>>> Point.mro()
[<class '__main__.Point'>, <class '__main__.Point'>, <type 'tuple'>, <type 'object'>]
# ^^^^^---------------------^^^^^-- same names!
这使我们能够在向他们求助时查看他们的意图:
Help on class NT in module __main__:
class NT(builtins.tuple)
| :param str foo: foo name
| :param list bar: List of bars to bar
...
与我们在Python2中完成相同任务的困难相比,这是非常简单的
Python 2
在Python2中,您需要
- 将namedtuple子类化,并
- 声明
\uuuu插槽\uuu==()
声明\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>是其他答案遗漏的一个重要部分
如果不声明\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
class Foo(namedtuple('Foo', 'bar')):
"""no __slots__ = ()!!!"""
现在:
>>> f = Foo('bar')
>>> f.bar
'bar'
>>> f.baz = 'what?'
>>> f.__dict__
{'baz': 'what?'}
当访问\uuuuu dict\uuuu
时,每个实例将创建一个单独的\uuuuuu dict\uuuuu
(缺少\uuuuu slot\uuuuuuu
不会妨碍功能,但元组的轻量级、不变性和声明的属性都是命名元组的重要特性)
如果希望命令行上的回显内容为您提供等效对象,您还需要一个\uuuu repr\uuu
:
NTBase = collections.namedtuple('NTBase', 'foo bar')
class NT(NTBase):
"""
Individual foo bar, a namedtuple
:param str foo: foo name
:param list bar: List of bars to bar
"""
__slots__ = ()
如果使用不同的名称创建基namedtuple,则需要这样的\uuuu repr\uuuuu
(就像我们在上面使用name字符串参数'NTBase'
所做的那样):
要测试repr,请实例化,然后测试传递到eval(repr(实例))
文档中的示例
请给出这样一个例子,关于\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
,我正在向其中添加我自己的docstring:
上面显示的子类将\uuuuuuuuuuuuuuuuuuuu
设置为空元组。这很有帮助
通过防止创建实例来降低内存需求
字典
这演示了就地使用(就像这里的另一个答案所建议的那样),但是请注意,如果您正在调试,当您查看方法解析顺序时,就地使用可能会变得混乱,这就是为什么我最初建议使用Base
作为Base namedtuple的后缀:
NT = collections.namedtuple('NT', 'foo bar')
NT.__doc__ = """:param str foo: foo name
:param list bar: List of bars to bar"""
>>> Point.mro()
[<class '__main__.Point'>, <class '__main__.Point'>, <type 'tuple'>, <type 'object'>]
# ^^^^^---------------------^^^^^-- same names!
>Point.mro()
[, , ]
#^^^^^------------------^^^^^^--同名!
要防止在从使用它的类进行子类化时创建\uuu dict\uuu
,还必须在子类中声明它。另请参见。自Python 3.5以来,可以更新namedtuple
对象的docstring
从:
在Python 3.6+中,您可以使用:
class Point(NamedTuple):
"""
A point in 2D space
"""
x: float
y: float
我创建此函数是为了快速创建命名元组,并记录元组及其每个参数:
from collections import namedtuple
def named_tuple(name, description='', **kwargs):
"""
A named tuple with docstring documentation of each of its parameters
:param str name: The named tuple's name
:param str description: The named tuple's description
:param kwargs: This named tuple's parameters' data with two different ways to describe said parameters. Format:
<pre>{
str: ( # The parameter's name
str, # The parameter's type
str # The parameter's description
),
str: str, # The parameter's name: the parameter's description
... # Any other parameters
}</pre>
:return: collections.namedtuple
"""
parameter_names = list(kwargs.keys())
result = namedtuple(name, ' '.join(parameter_names))
# If there are any parameters provided (such that this is not an empty named tuple)
if len(parameter_names):
# Add line spacing before describing this named tuple's parameters
if description is not '':
description += "\n"
# Go through each parameter provided and add it to the named tuple's docstring description
for parameter_name in parameter_names:
parameter_data = kwargs[parameter_name]
# Determine whether parameter type is included along with the description or
# if only a description was provided
parameter_type = ''
if isinstance(parameter_data, str):
parameter_description = parameter_data
else:
parameter_type, parameter_description = parameter_data
description += "\n:param {type}{name}: {description}".format(
type=parameter_type + ' ' if parameter_type else '',
name=parameter_name,
description=parameter_description
)
# Change the docstring specific to this parameter
getattr(result, parameter_name).__doc__ = parameter_description
# Set the docstring description for the resulting named tuple
result.__doc__ = description
return result
然后用您自己的数据实例化所描述的命名元组,即
Help on class MyTuple:
class MyTuple(builtins.tuple)
| MyTuple(x, y)
|
| My named tuple for x,y coordinates
|
| :param x: The x value
| :param y: The y value
|
| Method resolution order:
| MyTuple
| builtins.tuple
| builtins.object
|
| Methods defined here:
|
| __getnewargs__(self)
| Return self as a plain tuple. Used by copy and pickle.
|
| __repr__(self)
| Return a nicely formatted representation string
|
| _asdict(self)
| Return a new OrderedDict which maps field names to their values.
|
| _replace(_self, **kwds)
| Return a new MyTuple object replacing specified fields with new values
|
| ----------------------------------------------------------------------
| Class methods defined here:
|
| _make(iterable) from builtins.type
| Make a new MyTuple object from a sequence or iterable
|
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(_cls, x, y)
| Create new instance of MyTuple(x, y)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| x
| The x value
|
| y
| The y value
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| _fields = ('x', 'y')
|
| _fields_defaults = {}
|
| ----------------------------------------------------------------------
| Methods inherited from builtins.tuple:
|
| __add__(self, value, /)
| Return self+value.
|
| __contains__(self, key, /)
| Return key in self.
|
| __eq__(self, value, /)
| Return self==value.
|
| __ge__(self, value, /)
| Return self>=value.
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __getitem__(self, key, /)
| Return self[key].
|
| __gt__(self, value, /)
| Return self>value.
|
| __hash__(self, /)
| Return hash(self).
|
| __iter__(self, /)
| Implement iter(self).
|
| __le__(self, value, /)
| Return self<=value.
|
| __len__(self, /)
| Return len(self).
|
| __lt__(self, value, /)
| Return self<value.
|
| __mul__(self, value, /)
| Return self*value.
|
| __ne__(self, value, /)
| Return self!=value.
|
| __rmul__(self, value, /)
| Return value*self.
|
| count(self, value, /)
| Return number of occurrences of value.
|
| index(self, value, start=0, stop=9223372036854775807, /)
| Return first index of value.
|
| Raises ValueError if the value is not present.
通过python3命令行执行help(MyTuple)
时,如下所示:
MyTuple = named_tuple(
"MyTuple",
"My named tuple for x,y coordinates",
x=("int", "The x value"),
y=("int", "The y value")
)
注意:这仅对Python3有效。在Python2中:AttributeError:type对象的attribute'\uuuu doc\uuuuuuu'不可写
。虽然没有其他答案简洁明了,但这应该是公认的答案,因为它突出了\uuu slots\uuuuu
的重要性。如果没有它,您将失去namedtuple的轻量级值。在类中包含\uuuu slots\uuu=()
很重要。否则,您将为属性创建一个\uuu dict\uuu
,从而失去namedtuple的轻量级特性。子类化不会将namedtuple
转换为一个完整的“对象”吗?因此失去了命名元组带来的一些性能增益?如果将\uuuu slots\uuu=()
添加到派生的子类中,则可以保留使用namedtup的内存和性能优势
>>> Point.mro()
[<class '__main__.Point'>, <class '__main__.Point'>, <type 'tuple'>, <type 'object'>]
# ^^^^^---------------------^^^^^-- same names!
Point = namedtuple('Point', ['x', 'y'])
Point.__doc__ += ': Cartesian coodinate'
Point.x.__doc__ = 'abscissa'
Point.y.__doc__ = 'ordinate'
class Point(NamedTuple):
"""
A point in 2D space
"""
x: float
y: float
from collections import namedtuple
def named_tuple(name, description='', **kwargs):
"""
A named tuple with docstring documentation of each of its parameters
:param str name: The named tuple's name
:param str description: The named tuple's description
:param kwargs: This named tuple's parameters' data with two different ways to describe said parameters. Format:
<pre>{
str: ( # The parameter's name
str, # The parameter's type
str # The parameter's description
),
str: str, # The parameter's name: the parameter's description
... # Any other parameters
}</pre>
:return: collections.namedtuple
"""
parameter_names = list(kwargs.keys())
result = namedtuple(name, ' '.join(parameter_names))
# If there are any parameters provided (such that this is not an empty named tuple)
if len(parameter_names):
# Add line spacing before describing this named tuple's parameters
if description is not '':
description += "\n"
# Go through each parameter provided and add it to the named tuple's docstring description
for parameter_name in parameter_names:
parameter_data = kwargs[parameter_name]
# Determine whether parameter type is included along with the description or
# if only a description was provided
parameter_type = ''
if isinstance(parameter_data, str):
parameter_description = parameter_data
else:
parameter_type, parameter_description = parameter_data
description += "\n:param {type}{name}: {description}".format(
type=parameter_type + ' ' if parameter_type else '',
name=parameter_name,
description=parameter_description
)
# Change the docstring specific to this parameter
getattr(result, parameter_name).__doc__ = parameter_description
# Set the docstring description for the resulting named tuple
result.__doc__ = description
return result
MyTuple = named_tuple(
"MyTuple",
"My named tuple for x,y coordinates",
x="The x value",
y="The y value"
)
t = MyTuple(4, 8)
print(t) # prints: MyTuple(x=4, y=8)
Help on class MyTuple:
class MyTuple(builtins.tuple)
| MyTuple(x, y)
|
| My named tuple for x,y coordinates
|
| :param x: The x value
| :param y: The y value
|
| Method resolution order:
| MyTuple
| builtins.tuple
| builtins.object
|
| Methods defined here:
|
| __getnewargs__(self)
| Return self as a plain tuple. Used by copy and pickle.
|
| __repr__(self)
| Return a nicely formatted representation string
|
| _asdict(self)
| Return a new OrderedDict which maps field names to their values.
|
| _replace(_self, **kwds)
| Return a new MyTuple object replacing specified fields with new values
|
| ----------------------------------------------------------------------
| Class methods defined here:
|
| _make(iterable) from builtins.type
| Make a new MyTuple object from a sequence or iterable
|
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(_cls, x, y)
| Create new instance of MyTuple(x, y)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| x
| The x value
|
| y
| The y value
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| _fields = ('x', 'y')
|
| _fields_defaults = {}
|
| ----------------------------------------------------------------------
| Methods inherited from builtins.tuple:
|
| __add__(self, value, /)
| Return self+value.
|
| __contains__(self, key, /)
| Return key in self.
|
| __eq__(self, value, /)
| Return self==value.
|
| __ge__(self, value, /)
| Return self>=value.
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __getitem__(self, key, /)
| Return self[key].
|
| __gt__(self, value, /)
| Return self>value.
|
| __hash__(self, /)
| Return hash(self).
|
| __iter__(self, /)
| Implement iter(self).
|
| __le__(self, value, /)
| Return self<=value.
|
| __len__(self, /)
| Return len(self).
|
| __lt__(self, value, /)
| Return self<value.
|
| __mul__(self, value, /)
| Return self*value.
|
| __ne__(self, value, /)
| Return self!=value.
|
| __rmul__(self, value, /)
| Return value*self.
|
| count(self, value, /)
| Return number of occurrences of value.
|
| index(self, value, start=0, stop=9223372036854775807, /)
| Return first index of value.
|
| Raises ValueError if the value is not present.
MyTuple = named_tuple(
"MyTuple",
"My named tuple for x,y coordinates",
x=("int", "The x value"),
y=("int", "The y value")
)