将文档添加到namedtuples?
是否有可能以简单的方式添加一个文档string到一个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.__doc__ # -> "Point(x, y)" print Point2.__doc__ # -> "Point2(x, y)"
但是这并没有削减。 有可能以其他方式做?
你可以通过在namedtuple
的返回值周围创build一个简单的空的包装类来实现。 我创build的文件的内容( nt.py
):
from collections import namedtuple Point_ = namedtuple("Point", ["x", "y"]) class Point(Point_): """ A point in 2d space """ pass
然后在Python REPL中:
>>> print nt.Point.__doc__ A point in 2d space
或者你可以这样做:
>>> help(nt.Point) # which outputs...
类的帮助模块中的点nt: class级(Point) | 2d空间中的一个点 | | 方法parsing顺序: | 点 | 点 | __builtin __。元组 | __builtin __。对象 ...
如果你不喜欢每次都用手工做,那么编写一个工厂函数来做这件事是微不足道的:
def NamedTupleWithDocstring(docstring, *ntargs): nt = namedtuple(*ntargs) class NT(nt): __doc__ = docstring return NT Point3D = NamedTupleWithDocstring("A point in 3d space", "Point3d", ["x", "y", "z"]) p3 = Point3D(1,2,3) print p3.__doc__
其输出:
A point in 3d space
通过谷歌浏览这个老问题,同时想知道同样的事情。
只是想指出,你可以通过在类声明中直接调用namedtuple()来更好地整理它:
from collections import namedtuple class Point(namedtuple('Point', 'x y')): """Here is the docstring."""
在Python 3中,不需要包装,因为types的__doc__
属性是可写的。
from collections import namedtuple Point = namedtuple('Point', 'x y') Point.__doc__ = '''\ A 2-dimensional coordinate x - the abscissa y - the ordinate'''
这与标准类定义紧密相关,其中文档string在标题后面。
class Point(): '''A 2-dimensional coordinate x - the abscissa y - the ordinate''' <class code>
这在Python 2中不起作用。
AttributeError: attribute '__doc__' of 'type' objects is not writable
。
是否有可能以简单的方式添加一个文档string到一个namedtuple?
Python 3
在Python 3中,您可以轻松更改您的namedtuple上的文档:
NT = collections.namedtuple('NT', 'foo bar') NT.__doc__ = """:param str foo: foo name :param list bar: List of bars to bar"""
当我们打电话给他们时,我们可以查看他们的意图:
Help on class NT in module __main__: class NT(builtins.tuple) | :param str foo: foo name | :param list bar: List of bars to bar ...
与我们在Python 2中完成同样的事情相比,这非常简单。
Python 2
在Python 2中,你需要
- 子类的namedtuple,和
- 声明
__slots__ == ()
声明__slots__
是其他答案在这里错过的重要部分 。
如果你没有声明__slots__
– 你可以添加可变的ad-hoc属性到实例中,引入错误。
class Foo(namedtuple('Foo', 'bar')): """no __slots__ = ()!!!"""
现在:
>>> f = Foo('bar') >>> f.bar 'bar' >>> f.baz = 'what?' >>> f.__dict__ {'baz': 'what?'}
当访问__dict__
时,每个实例将创build一个单独的__dict__
__dict__
(缺less__slots__
不会妨碍function,但元组的轻量级,不可变性和声明的属性都是namedtuples的重要特性)。
如果你想要在命令行上回显给你一个等价的对象,你还需要一个__repr__
。
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__ = ()
像这样的__repr__
是需要的,如果你使用不同的名称创build基类namedtuple(就像我们上面用name string参数'NTBase'
):
def __repr__(self): return 'NT(foo={0}, bar={1})'.format( repr(self.foo), repr(self.bar))
为了testingrepr,实例化,然后testingpass是否等于eval(repr(instance))
nt = NT('foo', 'bar') assert eval(repr(nt)) == nt
来自文档的示例
文档也给出了这样一个例子,关于__slots__
– 我正在添加我自己的文档string:
class Point(namedtuple('Point', 'x y')): """Docstring added here, not in original""" __slots__ = () @property def hypot(self): return (self.x ** 2 + self.y ** 2) ** 0.5 def __str__(self): return 'Point: x=%6.3fy=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot)
…
上面显示的子类将
__slots__
设置为一个空元组。 这有助于防止创build实例字典,从而保持较低的内存要求。
这说明就地使用(就像这里提供的另一个答案一样),但是请注意,当您查看方法parsing顺序时,就地使用可能会变得混乱,如果您正在debugging,这就是为什么我最初build议使用Base
作为后缀名为:
>>> Point.mro() [<class '__main__.Point'>, <class '__main__.Point'>, <type 'tuple'>, <type 'object'>] # ^^^^^---------------------^^^^^-- same names!
为了防止从使用它的类__dict__
时创build__dict__
,还必须在子类中声明它。 有关使用__slots__
更多信息,另请参阅此答案 。
自Python 3.5以来,可以更新namedtuple
对象的文档string。
从最新消息来看:
Point = namedtuple('Point', ['x', 'y']) Point.__doc__ += ': Cartesian coodinate' Point.x.__doc__ = 'abscissa' Point.y.__doc__ = 'ordinate'
不需要使用接受的答案所build议的包装类。 简单地说就是添加一个文档string:
from collections import namedtuple Point = namedtuple("Point", ["x", "y"]) Point.__doc__="A point in 2D space"
这导致:(例如使用ipython3
):
In [1]: Point? Type: type String Form:<class '__main__.Point'> Docstring: A point in 2D space In [2]:
瞧!
你可以通过Raymond Hettinger 调用你自己的namedtuple工厂函数版本,并添加一个可选的docstring
参数。 然而,使用与配方中相同的基本技术来定义自己的工厂function会更容易,而且可以说更好。 无论哪种方式,你最终会得到可重用的东西。
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
不,您只能将文档string添加到模块,类和函数(包括方法)