В Python я могу определить именованный кортеж, используя typename?

Интересно, почему третья строка в фрагменте B вызовет ошибку. Насколько я понимаю, во второй строке фрагмента B (и A) я создал переменную класса (не экземпляр класса) cls_obj чей тип / имя класса Duck, Это как

class Duck(...):
    ...Code goes here

cls_obj=Duck

Поэтому я ожидал, что фрагменты A и B сработают, но фрагмент B потерпел неудачу! Что пошло не так?

# Snippet A
from collections import namedtuple
cls_obj=namedtuple('Duck', 'bill tail')
duck = cls_obj(bill='wide orange', tail='long')

# Snippet B
from collections import namedtuple
cls_obj=namedtuple('Duck', 'bill tail')
duck = Duck(bill='wide orange', tail='long')

1 ответ

Решение

В Python класс - это просто особый вид значения.

class Duck(object):
    pass

# 'Duck' is just a variable, you can change it
Duck = 3

x = Duck() # Fails!

Вы можете делать такие вещи:

>>> class Goat(object):
...     def __repr__(self):
...         return 'Goat()'
...
>>> Cow = Goat
>>> del Goat
>>> Goat()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'Goat' is not defined
>>> Cow()
Goat()
>>> Cow.__name__
'Goat'
>>> Cow().__class__
<class '__main__.Goat'>

Теперь, когда вы понимаете, что класс - это просто значение, все станет более понятным. namedtuple('Goat', ...) не то же самое, что class Goat, Он определяет класс, но не присваивает результирующее значение (сам класс) переменной в глобальной области видимости. Функции не могут этого сделать, и namedtuple() это обычная функция.

Другие вопросы по тегам