Добавление 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)"


но это не имеет значения. Можно ли это сделать каким-то другим способом?

444   9  

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

нет, вы можете добавлять только строки doc в модули, классы и функции (включая методы)

Comments

    Ничего не найдено.