Пам'ятаю недавно мене попросили про дивну: які питання можна задати 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, який вже половина рунета вивчила і я не став його включати в пост.