Открыть изображение »
Пара вопросов для Python-задрота
16 июня 2011 :: 18 комментариев :: 8909 просмотров :: 1112 слов

Помню недавно меня попросили о странном: какие вопросы можно задать Python-программисту, чтобы оценить его знания? Честно говоря, я не люблю подобные тесты, ибо все они сводятся либо в синтетику в вакууме, либо в знание определенных функций из документации и багов языков. Еще их обожают давать на всяких собеседованиях, где высшей степенью идиотизма явзяется запрет гуглить и писать все на листочке. Ну там типа "как сделать xor в питоне?". Ну хотя бы вспомните смешной топик на хабре про Senior PHP и мой несмешной ответ. Его хоть и заплюсовали, но я все равно получил за него, по-моему, -5 кармы от злых похапешников. Ну это еще хорошо, РНР'шники на хабре - самая озлобленная на всех остальных каста, редко склонная к самоиронии, так что обычно за срачи в РНР-топиках срубают больше. Но смысл моей иронии понятен - из трех вопросов по РНР, к РНР относится ноль. А так как любому хоть сколько-нибудь понимающему программисту обычно насрать на названия всех методов класса string, даже я до сих пор частенько подсматриваю их названия через bpython и ничего, жив, нужно что-то другое. Максимум, что я могу тут потерпеть, это вопросы типа "как вывести список всех полей и методов объекта, начинающихся на 'jopa'". Любой питонист ответит что-то из разряда:
>>> [x for x in dir("") if x.startswith("t")]
['title', 'translate']

Мой опыт хоть и скуден, но все же я успел найти для себя парочку любимых вопросов, которые люблю подсовывать начинающим питонистам.

Начнем с простого вопроса, чтобы просто определить - перед тобой свитчер с С++ или мальчик мануал хоть раз видел.

Как отсортировать два списка по элементам второго?

Если задумался или не знает - быть может все плохо, а может просто забыл. Если начал писать свой qsort, то это студент-второкурсник. Самый python-way ответ:
>>> a = [1, 3, 2]
>>> b = [11, 33, 22]
>>> sorted(zip(a, b), key=lambda x: x[1])
[(1, 11), (2, 22), (3, 33)]

Вопрос как раз таки на знание синтаксиса, но на правильное знание. Тут тебе и любимый sorted(), и lambda, и zip(). Джентельменский набор, без него никуда.

upd: в третьем Python убрали аргумент key, оставив только cmp. Так что можно еще и вот так:
sorted(zip(a, b), cmp=lambda x, y: x[1] - y[1])

upd2: Ошибочка, в третьем питоне убрали как раз cmp. Так что:
sorted(iterable, key=None, reverse=False)

Напиши цикл for от 1 до 100000000000000000000000

Это мой любимый вопрос, который я услышал где-то на Яндексе, и с тех пор полюбил. Даже я с первого раза не понял в чем подвох и написал как обычно for i in xrange(...). Вопрос как раз на "глубинную" суть Python. Потому что некоторые считают, что если убрали типы данных, указатели и другую хренотень, теперь можно делать что угодно. А нет. Сделайте:
>>> from sys import maxint
>>> maxint
9223372036854775807

И увидите, что int в python ограничен. Вау. Чудес и бесконечных интов не бывает. А range и xrange при передаче в них параметра, прогоняют его через int(). Так что при таком красивом вызове все ебанется. Этим вопрос и хорош. Сразу показывает боится ли человек генераторов или нет и знает ли что-то о типах данных. Короче правильный ответ: "написать простейший генератор". Этого достаточно. Если труЪ, то напишет что-то типа:
>>> def gen(a):
... while a > 0:
... a -= 1
... yield a
...
>>> list(gen(20))
[19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Что будет...

...если выполнить код:
>>> a = [[]]*3
>>> a[0].append(42)
>>> print a

а главное - почему?

Если не знает, что значит [[]]*3 - скорее всего на вопрос не ответит (даже с подсказкой, что это создается список из трех списков), ну чтож, не смертельно, будем знать чему учить, однако если знает - должен заметить подвох. Создаем список из трех списков, в первый вставляем 42, казалось бы все хорошо. На этот камень я наткнулся первый раз, когда писал курсовик.

Правильный ответ:
[[42], [42], [42]]

Да-да, все созданные внутри списки - это указатели на один и тот же объект. В этом и подвох. Здравствуй, С/С++.

Чем отличаются () от [] в списковых выражениях?

Ну то есть чем [x for x in lst] отличается от (x for x in lst). Я был удивлен, но очень многие этого не знают. Тут уже да, на знание языка. Первое - сразу возвращает список, второе - объект-генератор этого списка.

Как написать синглетон?

По-моему любимый вопрос всех питонистов. Когда я готовил этот текст и спрашивал знакомых, 100% из них предложили в том числе и этот вопрос. Но я не отрицаю, вопрос действительно хороший и именно на особенности самого языка. Тут снова несколько вариантов ответа:
1) "А чо такое синглетон?" Тут сразу все понятно, "банду четырех" в руки и грызть гранит науки.
2) Начнет писать свой класс с get_instance() и попытками сделать конструктор приватным. Ну, если вы хотите поиздеваться, то можно даже наблюдать за этим. Однако лучше сразу остановить и научить последнему пункту.
3) Начнет писать синглетон на метаклассах. Такое встречается редко и достойно уважения, потому что любой, кто смог осилить метаклассы python, уже может делать себе наколку со змеей. Но как бы это не было круто, это - колоть орехи ядерным взрывом.
4) Модуль в python - это уже синглетон. Создаем модуль, где угодно в нем, хоть в init.py объявляем всю нашу функциональность, а затем import module as my_cool_single. Готово. Новые import ничего не изменят.

Что произойдет и почему?

Вот код:
>>> a = [1, 2, 3, 4, 5]
>>> for x in a:
... del x

Казалось бы все читаемо и круто. Несмотря на 1, 2, 3... - это все же объекты, их можно удалять. И ничего не предвещало беды, только вот. Ничего не произойдет. Список окажется нетронутым. Главное тут - почему? Честно говоря, я не читал официальных док по этому и все забыл, однако я бы рассуждал так:

  • Список хранит указатели на объекты. Объекты хранятся где-то еще в памяти. При переборе списка for'ом, мы создаем еще один указатель на элемент списка - х. Теперь у нас два указателя. В Python используется сборщик мусора со счетчиком ссылок (кстати, можно попросить объяснить почему это плохо). Когда мы делаем del x - мы разыменовываем только один указатель. Второй остается. Сборка мусора не запустится, ничего не произойдет. Гуру ведь меня поправят, если я не прав?

Ну именно поэтому такой код все-таки прокатит:
>>> a = [1, 2, 3, 4]
>>> while a:
... del a[0]
...
...
>>> a
[]

После ответа еще можно спросить "а как сделать это нормально?" Ну и посмотреть знает ли человек разницу между del a и del a[:].

Написать декоратор, выводящий время выполнения функции

Ну и мы совсем упустили вопросы на знание декораторов. Поэтому вот такой простенький вопросик на них и модуль datetime. Нет, тут нет никаких подводных камней. Просто запомнить до и после. Дать человеку гугл и чтобы реализовал. Код приводить не буду, домашнее задание :3

А какие еще подобные вопросы есть? Ну, кроме любимого fazzbazz, который уже половина рунета выучила и я не стал его включать в пост.

Еще? Тогда вот
Комментарии
0
Un1oR ⸬ 16 июня 2011, 11:32 ⸬ Novosibirsk, RU ⸬ Linux лог
#
> Как отсортировать два списка по элементам первого?
Чо-то я не совсем вопрос понял. Грубо говоря просто один список - kyes, второй - values, и x[i] => y[i]? Или что имелось ввиду?
0
vas3k ⸬ 16 июня 2011, 11:41 ⸬ Novosibirsk, RU ⸬ Linux лог
#
Un1oR, да, ты все правильно понял. keys -> values.
0
мальчик с фпми ⸬ 16 июня 2011, 11:53 ⸬ Novosibirsk, RU ⸬ Windows лог
#
В первом sorted(zip(a b)) достаточно же, туплы по умолчанию сортируются как надо.
Вопросики тут какие-то есть: http://pyobject.ru/blog/2010/02/04/python-quiz/

Мой любимый вопрос, кстати, такой (хоть это все и знают). Что будет в каждом из случаев:
1) print 1j < 1j
2) print 1j < None
Продуманность дизайна языка, типа.
0
vas3k ⸬ 16 июня 2011, 12:10 ⸬ Novosibirsk, RU ⸬ Linux лог
#
мальчик с фпми, да, мой фейл, не проверил. Приду домой, исправлю на x[1].
0
uɐɯnɥǝɹǝʍ ⸬ 16 июня 2011, 14:32 ⸬ Novosibirsk, RU ⸬ Linux лог
#
> Максимум, что я могу тут потерпеть, это вопросы типа "как вывести список всех методов объекта, начинающихся на 'jopa'"
[x for x in obj.__dict__.keys() if callable(x) and x.__name__.startswith("jopa")] # Не подглядывая никуда. Хер его знает, работает ли.

Про maxint не знал, позор на мою голову.

> Как написать синглетон?
Ох, без гугла мне было бы тяжело. Попробовал бы переопределить __new__ и хранить объект внутри cls

> Попробовал бы переопределить __new__ и хранить объект внутри cls
И ничего не получил таким образом. http://goo.gl/LCl0h

> Мой любимый вопрос, кстати, такой (хоть это все и знают)
Знаю о комплексных числах, но ни разу ими не пользовался.
0
Hanggard ⸬ 17 июня 2011, 10:20 ⸬ Novosibirsk, RU ⸬ Windows лог
#
Мало кто знает, что среди книг валялись кучи говна)
0
o_Ohmy ⸬ 19 июня 2011, 15:48 ⸬ Novosibirsk, RU ⸬ Windows лог
#
еще больше захотелось взяться за питон...
0
Артур ⸬ 05 августа 2011, 08:14 ⸬ Novosibirsk, RU ⸬ Windows лог
#
Спасибо.
0
adw0rd ⸬ 22 февраля 2012, 11:17 ⸬ Saint Petersburg, RU ⸬ Linux лог
#
>>> upd: в третьем Python убрали аргумент key, оставив только cmp.

Вообщето в 3-ем питоне убрали cmp, а key оставили:
sorted(iterable, key=None, reverse=False) --> new sorted list
0
vas3k ⸬ 22 февраля 2012, 14:47 ⸬ Novosibirsk, RU ⸬ Apple лог
#
adw0rd, спасибо за поправку, почему-то я был уверен до последнего, что именно cmp оставили. Сам пока не лезу в третий Python.
0
dmitrysbor ⸬ 31 марта 2014, 17:06 ⸬ Saint Petersburg, RU ⸬ Linux лог
#
>Как отсортировать два списка по элементам второго?
Зачем там нужна lambda?

Прекрасно работает вот так:
sorted(zip(a, b))
0
vas3k ⸬ 01 апреля 2014, 03:06 ⸬ Novosibirsk, RU ⸬ Apple лог
#
dmitrysbor, прекрасно работает, только сортирует по значениям первого, а не второго списка как указано в задании:

>>> a = [1, 2, 3]
>>> b = [22, 33, 11]
>>> sorted(zip(a, b))
[(1, 22), (2, 33), (3, 11)]
>>> sorted(zip(a, b), key=lambda x: x[1])
[(3, 11), (1, 22), (2, 33)]
>>>
0
Эль ⸬ 15 мая 2018, 10:07 ⸬ BY ⸬ Linux лог
#
vas3k, а как насчёт sorted(zip(b, a))?

slowpoke.jpg
(не заполняйте это поле)

me@vas3k.ru :: telegram :: twitter :: instagram :: facebook :: github