Добавление docstrings в namedtuples?
можно ли легко добавить строку документации в 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)"
но это не имеет значения. Можно ли это сделать каким-то другим способом?
9 ответов:
вы можете достичь этого, создав простой, пустой класс-оболочку вокруг возвращаемого значения из
namedtuple. Содержимое файла, который я создал (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...Help on class Point in module nt: class Point(Point) | A point in 2d space | | Method resolution order: | Point | Point | __builtin__.tuple | __builtin__.object ...Если вам не нравится делать это вручную каждый раз, тривиально написать своего рода заводскую функцию для этого:
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
наткнулся на этот старый вопрос через Google, задаваясь тем же вопросом.
просто хотел отметить, что вы можете привести его в порядок еще больше, вызвав namedtuple() прямо из объявления класса:
from collections import namedtuple class Point(namedtuple('Point', 'x y')): """Here is the docstring."""
в Python 3 не требуется обертка, так как
__doc__атрибуты типов записи.from collections import namedtuple Point = namedtuple('Point', 'x y') Point.__doc__ = '''\ A 2-dimensional coordinate x - the abscissa y - the ordinate'''это близко соответствует стандартному определению класса, где строка документа следует за заголовком.
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.
можно ли легко добавить строку документации в 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__- вы можете добавить изменяемые специальные атрибуты к экземплярам, вводя ошибки.class Foo(namedtuple('Foo', 'bar')): """no __slots__ = ()!!!"""и так:
>>> f = Foo('bar') >>> f.bar 'bar' >>> f.baz = 'what?' >>> f.__dict__ {'baz': 'what?'}каждый экземпляр будет создавать отдельный
__dict__, когда__dict__доступ (отсутствие__slots__в противном случае не будет препятствовать функциональности, но легковесность кортежа, неизменность и объявленные атрибуты-все это важные функции 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__ = ()a
__repr__как это необходимо, если вы создаете базу namedtuple с другим именем (как мы делали выше с имя строкового аргумента,'NTBase'):def __repr__(self): return 'NT(foo={0}, bar={1})'.format( repr(self.foo), repr(self.bar))чтобы проверить repr, создать экземпляр, а затем проверить на равенство прохода к
eval(repr(instance))nt = NT('foo', 'bar') assert eval(repr(nt)) == ntпример из документации
The docs также приведите такой пример, относительно
__slots__- я добавляю к нему свою собственную строку документа: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.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot)...
подкласс, показанный выше, устанавливает
__slots__к пустому кортежу. Эта помощь сохранить требования к памяти низкий, предотвращая создание экземпляра словари.это демонстрирует использование на месте (как и другой ответ здесь предлагает), но обратите внимание, что использование на месте может стать запутанным, когда вы смотрите на порядок разрешения метода, если вы отлаживаете, поэтому я изначально предложил использовать
Baseв качестве суффикса для базового namedtuple:>>> Point.mro() [<class '__main__.Point'>, <class '__main__.Point'>, <type 'tuple'>, <type 'object'>] # ^^^^^---------------------^^^^^-- same names!чтобы предотвратить создание
__dict__при создании подклассов из класса, который его использует, необходимо также объявить это в подклассе. Смотрите также этот ответ для получения дополнительных предостережений об использовании__slots__.
начиная с Python 3.5, docstrings для
namedtupleобъекты могут быть обновлены.С whatsnew:
Point = namedtuple('Point', ['x', 'y']) Point.__doc__ += ': Cartesian coodinate' Point.x.__doc__ = 'abscissa' Point.y.__doc__ = 'ordinate'
нет необходимости использовать класс-оболочку, как это предлагается в принятом ответе. Просто буквально добавить является строкой документации:
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]:вуаля!
вы могли бы придумать свой вариант функция фабрики namedtuple Раймонда Хеттингера и добавить дополнительный
в Python 3.6+ вы можете использовать:
class Point(NamedTuple): """ A point in 2D space """ x: float y: float
Comments