2015-03-31 8 views
6

При чтении ответа fmark «s на вопрос What are "named tuples" in Python? я увидел, что пример, приведенный там было такое же имя и ссылку, то есть слово Point появляется дважды в следующем заявлении:
Может ли другое имя и ссылка названного кортежа быть другим?

Point = namedtuple('Point', 'x y')

Так что я пошел в оригинальной ссылке:
https://docs.python.org/2/library/collections.html#collections.namedtuple
И здесь я нашел еще два примера:

EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade') 
Color = namedtuple('Color', 'red green blue') 

В идеале слова не повторяются в Python. Например вся линия (для в Point примере) может быть заменен следующим:

namedtuple('Point', 'x y') 

ИЛИ

Point = namedtuple('x y') 

Конечно, это при условии, что названный кортеж должен иметь тот же имя и ссылку. Поэтому мой вопрос: когда целесообразно (если вообще разрешено), что именованный кортеж должен иметь другое имя и ссылку? Мне еще предстоит встретить пример.

+1

'namedtuple ('Point' ...)' создает класс под названием «Point», однако без присвоения ему некоторого идентификатора вы можете использовать его только один раз, например. 'point1 = namedtuple ('Point', 'x y') (1, 0)', а 'type (point1) - '. Удобно использовать идентификатор, который соответствует имени класса, но он не требуется, например. 'Vertex = namedtuple ('Point' ...)'. Класс - это еще один объект в python, и вы использовали бы другое имя в любое время, когда вы назначили бы другой идентификатор имени класса, например. 'class Point: ... Vertex = Point' – AChampion

+2

На мой взгляд, модуль' namedtuple' является ужасным беспорядком и должен был быть написан с использованием метаклассов в первую очередь. Мне все еще не ясно [почему это не так) (http://stackoverflow.com/questions/28184531), но если бы это было так, у вас была бы возможность использовать определения классов для вас по именам кортежей, обозначение метакласса, не требующее повторения имени класса. –

ответ

10

Вы можете сделать это, это просто вас раздражает.

In [1]: import collections 

In [2]: Point = collections.namedtuple('Rectangle', 'x y') 

In [3]: Point(1, 2) 
Out[3]: Rectangle(x=1, y=2) 

Это смущает, не делайте этого, если у вас нет веской причины.

Причина, по которой это происходит, состоит в том, что namedtuple() - это просто функция, она не имеет специальных знаний о том, как она используется в качестве декларации. В языках с макросами namedtuple() будет макросом, который вместо этого расширится. Таким образом, вместо того, чтобы придерживаться макросистемы или ходить в стек вызовов для имени, вам нужно указать имя дважды.

Так что это один из «бородавок» Python или компромисс с дизайном в зависимости от того, как вы к этому относитесь.

+1

Более конкретно: причина, по которой это происходит, - 'namedtuple', была написана с использованием' exec' и форматирования строк вместо использования метаклассов (которые имеют первый аргумент 'name', связанный с указанным именем экземпляра метакласса). Почему это? [Кто знает.] (Http://stackoverflow.com/questions/28184531/why-doesnt-the-namedtuple-module-use-a-metaclass-to-create-nt-class-objects) –

+0

Хотя, честно говоря, вам все равно придется повторять имя класса при использовании метакласса в качестве фабрики классов (например, 'type ('name', (object,), {})'). –