将文档添加到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添加到模块,类和函数(包括方法)