Страницы

Поиск по вопросам

вторник, 28 января 2020 г.

Почему атрибут ведёт себя как функция

#python


Натолкнулся на следующего формата код:

>>> from collections import namedtuple
>>> Duck = namedtuple('Duck', 'bill tail')
>>> duck = Duck('wide orange', 'long')
>>> duck
Duck(bill='wide orange', tail='long')


Мы присвоили результат работы функции namedtuple атрибуту Duck, который затем непонятным
для меня образом стал вызываться как функция, в которую к тому же ещё передали аргументы.
Второй вопрос связан с первым параметром функции namedtuple. Говорится, что туда передаётся
имя, но где оно конкретно отражается, ведь мы уже имеем атрибут с данным названием.
Буду благодарен за обьяснения.
    


Ответы

Ответ 1



namedtuple() возвращает новый подкласс кортежа с именованными полями. Здесь Duck - имя типа. Теперь, когда вы вызываете namedtuple('Duck', 'bill tail'), создается именованный кортеж. Класс с именем Duck создается внутри. Если к вызову добавить параметр verbose=True вы сможете все это увидеть: from collections import namedtuple Duck = namedtuple('Duck', 'bill tail', verbose=True) выведет: from builtins import property as _property, tuple as _tuple from operator import itemgetter as _itemgetter from collections import OrderedDict class Duck(tuple): 'Duck(bill, tail)' __slots__ = () _fields = ('bill', 'tail') def __new__(_cls, bill, tail): 'Create new instance of Duck(bill, tail)' return _tuple.__new__(_cls, (bill, tail)) ... Теперь, когда вы пишите duck = Duck('wide orange', 'long') вызывается конструктор класса Duck и для этого и нужно это имя. Если вы посмотрите тип созданного объекта type(duck), то увидите: >>>__main__.Duck UPD Пишут, что начиная с 3.7, параметр verbose и атрибут _source удалили.

Ответ 2



Функция в качестве своего результата может возвращать всё что угодно. Например, другую функцию или класс (а классы так же как и функции можно вызвать). В данном случае namedtuple возвращает как-раз таки класс. Поэтому результат вызова функции namedtuple можно вызвать. Имя нужно передать вот для чего: когда namedtuple создаёт класс, она не может знать, что после создания результат её работы будет присвоен переменной Duck. Но при создании ей уже нужно знать, с каким именем создавать класс. Поэтому приходится передавать имя в качестве аргумента.

Ответ 3



Duck - не атрибут, а переменная. Переменные хранят значения. Значениями в Python являются в том числе вызываемые объекты, например классы или функции. В данном случае функция namedtuple вернула класс, который был записан в переменную Duck. Имя, переданное в функцию namedtuple выступает именем класса, которое, в частности выводится при переводе объекта этого класса в строку (например, при выводе через print). В общем случае, имя переданное в namedtuple может не совпадать с именем переменной, в которую вы записали сформированный класс.

Комментариев нет:

Отправить комментарий