2015-05-29 8 views
3

Мы используем namedtuple так:В чем первый аргумент использования namedtuple?

>>> from collections import namedtuple 
>>> Point = namedtuple('Point', ['x', 'y']) 
>>> p=Point(1,2) 
>>> p.x 
1 

Я нашел первый аргумент namedtuple кажется бесполезным, так как:

Во-первых, мы не можем использовать его (для создания экземпляра, например):

>>> from collections import namedtuple 
>>> P = namedtuple('Point', ['x', 'y']) 
>>> p = Point(1,2) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'Point' is not defined 

Во-вторых, кажется, нет ограничений для него (например, мы не должны сделать его уникальным):

>>> P1 = namedtuple('Point', ['x', 'y']) 
>>> P2 = namedtuple('Point', ['x', 'y', 'z']) 
>>> p1 = P1(1,2) 
>>> p2 = P2(1,2,3) 
>>> p1 
Point(x=1, y=2) 
>>> p2 
Point(x=1, y=2, z=3) 

Я не нашел объяснений от manual или по поисковому запросу. Существует соответствующий вопрос here, но он не ответил, почему namedtuple нужен первый аргумент и как его можно использовать или когда это необходимо.

+2

Подумайте об этом - если у класса * не было '__name__', что бы выглядело' repr'? Если вы установите 'ClassName = namedtuple ('ClassName', ...)', то вы можете использовать, например. 'eval', чтобы воссоздать данный экземпляр. – jonrsharpe

+0

Как вы думаете, откуда взялось название от namedtuple? –

+0

@jonrsharpe У меня было недоразумение в отношении названий классов раньше, я думал, что они должны быть уникальными. – WKPlus

ответ

7

Он задает имя создаваемого класса:

>>> from collections import namedtuple 
>>> Point = namedtuple('Point', ['x', 'y']) 
>>> Point 
<class '__main__.Point'> 
>>> Point = namedtuple('Foobar', ['x', 'y']) 
>>> Point 
<class '__main__.Foobar'> 

Point имя в ваших глобалов просто ссылка на сгенерированный класс, класс сам необходимо иметь имя. Имя не может быть взято из переменной, которой назначен объект, поскольку класс генерируется сначала и только , а затем, назначенный отдельным шагом (после возврата вызова namedtuple()).

Он не должен быть уникальным в том же образом, что имя класса не должны быть уникальными при использовании class:

>>> class Foo(object): 
...  pass 
... 
>>> Bar = Foo 
>>> class Foo(object): 
...  pass 
... 
>>> Bar 
<class '__main__.Foo'> 
>>> Foo 
<class '__main__.Foo'> 

Вы обычно избегают такого рода вещи, сохраняя имена уникальными для каждого модуль, но вы не есть to.

Это имя предназначено для целей отладки; в tracebacks и в repr() выведено имя, которое поможет вам выяснить, какой класс используется.

To Python, это не имеет значения, если сгенерированный класс повторно использует имя. Это относится к модулю pickle; если вам нужно рассортировать экземпляры класса с именем tuple, убедитесь, что вы выбрали имя, соответствующее глобальному, по которому pickle может позже загрузить его снова. Но если повторное использование имени имеет смысл для вас или не препятствует разработке или отладке кода, то, во что бы то ни стало, повторно используйте имя или выберите что угодно.

+0

Но когда я определяю два именованных кортежа с тем же именем, он отлично работает, почему? – WKPlus

+0

@WKPlus почему * не будет * это? – jonrsharpe

+0

@WKPlus: Я могу создать несколько классов с тем же именем. Или функции. Для целей отладки и ясности вы хотите сохранить их уникальными, но они не применяются. –