Типы данных, основные конструкции. Python.
Первая пачка ответов на вопросы из какого-то собеседования, линк к сожалению потерялся. В принципе вопросы довольно простые, если знать немножко про функциональное программирование и ориентироваться в стандартных функциях.
1. Как получить список всех атрибутов объекта?
Очень просто, используя стандартную функцию dir. В качестве аргумента передаем тот самый объект, в данном случае (для примера) объект string.
Модуль inspect предоставляет несколько очень полезных методов которые позволяют собирать информацию о объектах Python, это достаточно важно, т.к. питон динамический ЯП и в нем очень просто сделать вещи которые обычно называют «хакерскими». Используя inspect можно получить содержимое класса, получить исходный код метода (ага, и поменять его), выделить формат и список аргументов функции и т.д.
2. Как получить список всех публичных атрибутов объекта?
Private методы в Python начинаются с «__» поэтому все что нужно сделать чтобы получить список public аттрибутов это отфильтровать все, что начинается с «__». Тут будет уместно использовать элемент функционального программирования — функцию filter(f, lst) которая формирует новый список элементов последовательности — lst руководствуясь функцией f.
3. Как получить список методов объекта?
Используя функцию callable() которая как бы говорит реально ли вызвать объект или нет. если вызвать реально — то это метод, если нет — то свойство
How to get a complete list of object's methods and attributes? [duplicate]
does not return pattern as one of the lists’s elements. Namely it returns:
According to the manual, it is supposed to contain
the object’s attributes’ names, the names of its class’s attributes, and recursively of the attributes of its class’s base classes.
It says also that
The list is not necessarily complete.
Is there a way to get the complete list? I always assumed that dir returns a complete list but apparently it does not.
Also: is there a way to list only attributes? Or only methods?
Edit: this is actually a bug in python -> supposedly it is fixed in the 3.0 branch (and perhaps also in 2.6)
5 Answers 5
For the complete list of attributes, the short answer is: no. The problem is that the attributes are actually defined as the arguments accepted by the getattr built-in function. As the user can reimplement __getattr__ , suddenly allowing any kind of attribute, there is no possible generic way to generate that list. The dir function returns the keys in the __dict__ attribute, i.e. all the attributes accessible if the __getattr__ method is not reimplemented.
For the second question, it does not really make sense. Actually, methods are callable attributes, nothing more. You could though filter callable attributes, and, using the inspect module determine the class methods, methods or functions.
That is why the new __dir__() method has been added in python 2.6
-
(scroll down a little bit)
Here is a practical addition to the answers of PierreBdR and Moe:
-
For Python >= 2.6 and new-style classes, dir() seems to be enough.
For old-style classes, we can at least do what a standard module does to support tab completion: in addition to dir() , look for __class__ , and then to go for its __bases__ :
(Test code and output are deleted for brevity, but basically for new-style objects we seem to have the same results for get_object_attrs() as for dir() , and for old-style classes the main addition to the dir() output seem to be the __class__ attribute.)
Only to supplement:
-
dir() is the most powerful/fundamental tool. (Most recommended)
Solutions other than dir() merely provide their way of dealing the output of dir() .
Listing 2nd level attributes or not, it is important to do the sifting by yourself, because sometimes you may want to sift out internal vars with leading underscores __ , but sometimes you may well need the __doc__ doc-string.
IMPORTANT: __dir__() can be sometimes overwritten with a function, value or type, by the author for whatever purpose.
Here is an example:
TypeError: descriptor __dir__ of ‘object’ object needs an argument
The author of PyTorch modified the __dir__() method to something that requires an argument. This modification makes dir() fail.
If you want a reliable scheme to traverse all attributes of an object, do remember that every pythonic standard can be overridden and may not hold, and every convention may be unreliable.
Как получить полный список методов и атрибутов объекта?
не возвращает шаблон как один из элементов списка. А именно, он возвращает:
Согласно руководству, предполагается, что он содержит
имена атрибутов объекта, имена его атрибутов класса и рекурсивно атрибутов его класса.
В нем также говорится, что
Список не обязательно завершен.
Есть ли способ получить список полный? Я всегда предполагал, что dir возвращает полный список, но, по-видимому, он не.
Также: есть ли способ перечислять только атрибуты? Или только методы?
Изменить: это на самом деле ошибка в python → предположительно, она исправлена в ветке 3.0 (и, возможно, также в версии 2.6)
4 ответа
Для полного списка атрибутов короткий ответ: no. Проблема в том, что атрибуты фактически определяются как аргументы, принятые встроенной функцией getattr . Так как пользователь может переопределить __getattr__ , внезапно разрешая любой атрибут, нет возможности генерировать этот список. Функция dir возвращает ключи в атрибуте __dict__ , т.е. Все доступные атрибуты, если метод __getattr__ не переопределяется.
Во втором вопросе это не имеет смысла. На самом деле, методы являются атрибутами, подлежащими вызову, и ничего больше. Вы можете фильтровать вызываемые атрибуты и, используя модуль inspect , определить методы, методы или функции класса.
Ответы на вопросы с PyObject
Для удобства проверки создадим небольшой тестовый класс:
1. Как получить список всех атрибутов объекта
2. Как получить список всех публичных атрибутов объекта
В Python для обозначения protected атрибутов используют "_", для private — "__" перед названием переменной. Следовательно, для получения списка только публичных атрибутов, список все атрибутов нужно отфильтровать. Сделать это можно или с помощью списковых выражений (list comprehension):
или воспользоваться функцией filter:
Как по мне, то первый вариант является более предпочтительным по причине большей читабельности.
3. Как получить список методов объекта
Поскольку функции и методы в Python являются объектами первого рода (вроде правильно написал?), то для проверки будем использовать функцию getattr, которая возвращает сам аттрибут объекта и функцию callable, которая и осуществляет проверку.
4. В какой «магической» переменной хранится содержимое help?
В атрибуте __doc__. В данную переменную заносится комментарий сразу после
объявления класса/метода/функции (см. тестовый класс).
Так же можно воспользоваться функцией help в интерактивном режиме:
5. Есть два кортежа, получить третий как конкатенацию первых двух
6. Есть два кортежа, получить третий как объединение уникальных элементов первых двух кортежей
В данном задании я видел 2 подхода:
1. писать циклы для проверки вхождения элемента в кортежи
2. воспользоваться встроенным типом set (по сути — хеш), над которым можно применять логические операции.
Решение с использованием второго подхода (используется XOR):
7. Почему если в цикле меняется список, то используется for x in lst[:], что означает [:]?
[:] — обозначение среза в питоне. Про них можно почитать, например, тут. В кратце: [:] создает копию lst и изменения в первом никак не влияют на итерацию по исходным значениям.
8. Есть два списка одинаковой длины, в одном ключи, в другом значения. Составить словарь.
Будем использовать функцию zip, которая делает кортежи из пары значений и dict, которая создает словарь из переданных аргументов.
9. Есть два списка разной длины, в одном ключи, в другом значения. Составить словарь. Для ключей, для которых нет значений использовать None в качестве значения. Значения, для которых нет ключей игнорировать.
В данном случае будем использовать функции zip, map. Особенностью zip является то, что возвращаемый результат ограничен самым коротким итерируемым. То есть это прекрасно подходит нам для случая, когда значений больше чем ключей. Во второй ветке python у map есть одна документированная особенность, а именно — если какое-либо из итерируемых значений короче других, оно дополняется с помощью None. Если вместо функции передано None, выполняется объединение и на выходе мы получаем те же кортежи.
Как вариант, можно рассмотреть использование функции itertools.izip_longest, которая была добавлена в 2.6.
10.Есть словарь. Инвертировать его. Т.е. пары ключ: значение поменять местами — значение: ключ.
Как вариант — опять использовать функцию zip.
P.S. прошу гуру подсказать, что правильней использовать в данном случае — zip или itertools.izip. Тоже самое относится и к values/itervalues.
11. Есть строка в юникоде, получить 8-битную строку в кодировке utf-8 и cp1251
Писал прямо во время написания статьи, но если правильно понял задание, то:
12. Есть строка в кодировке cp1251, получить юникодную строку
Аналогично:
Функции
1. Написать функцию, которой можно передавать аргументы либо списком/кортежем, либо по одному. Функция производит суммирование всех аргументов.
Решение вижу следующим: итерация по переданному списку. В случае если элемент списка — имеет атрибут __len__, а значит является итерируемым, разворачиваем его и передаем в нашу функцию.
2. Написать функцию-фабрику, которая будет возвращать функцию сложения с аргументом.
Так как функции являются объектами первого рода (если лажать, так по-крупному), то одними из вариантов их использования являются возврат их из других функций или методов и передача в качестве в аргументов. Суть сводится к тому, что мы должны вернуть функцию сложения, один из аргументов
которой задан при ее создании, а второй может варьироваться. Как я понимаю, это — замыкание — доступ к переменным, объявленным вне тела функции.
3. Написать фабрику, аналогичную п.2, но возвращающей список таких функций
В данном случае есть смысл возвращать список функций, которые мы написали выше.
Выглядеть будет примерно так:
4. Написать аналог map:
— первым аргументом идет либо функция, либо список функций
— вторым аргументом — список аргументов, которые будут переданы функциям
— полагается, что эти функции — функции одного аргумента
Данное задание я реализовал с использованием встроенного map (как вариант — заменен циклом). Так же, для проверки типа переданного значения использовал функцию isinstance и модуль collections, как аналог hasattr и магическому методу __len__.
Итераторы
Маленькое отступление. Я не видел особого смысла писать код итераторов, т.к. их код описан в документации к модулю itertools. Врядли я напишу лучше.
Итераторы основываются на генераторах, о которых есть прекрасная статья.
Модули
1. У нас есть импортированный модуль foo, как узнать физический путь файла, откуда он импортирован?
Путь хранится в аттрибуте __file__ модуля.
2. Из модуля foo вы импортируете модуль feedparser. Версия X feedparser’а есть в общесистемном каталоге site-packages, версия Y — рядом с модулем foo. Определена переменная окружения PYTHONPATH, и там тоже есть feedparser, версии Z. Какая версия будет использоваться?
Будет импортирована версия Y.
Согласно документации (6 раздел туториала), порядок импорта следующий:
1. директория рядом со скриптом, который был запущен
2. PYTHONPATH
3. системный каталог
3. Как посмотреть список каталогов, в которых Python ищет модули?
4. У вас есть модуль foo, внутри него импортируется модуль bar. Рядом с модулем foo есть файлы bar.py и bar/__init__.py Какой модуль будет использоваться.
Будет использован второй, т.е. пакет. Как я понял, происходит рекурсивный обход директорий, и пакеты импортируются первыми.
5. Что означает и для чего используется конструкция __name__ == ‘__main__’
Используется для определения был ли файл импортирован или запущен. Если мы его запускаем, то значение будет __main__, если импортируем — имя модуля.