Программисты тоже умеют развлекаться, так что давайте сегодня развлечемся и напишем quine (квайн). Квайн – это такая программа, которая выводит на экран свой же код, ни больше, ни меньше. Сразу договоримся, что пустая программа на Python, которая ничего не выводит, не считается квайном; это не интересно.
В Python у нас есть чудо-переменная, которая хранит путь к текущему интерпретируемому файлу, поэтому можно сделать так:
print(open(__file__).read())
Эта программа открывает свой же файл, читает и печатает его целиком. Но это жульничество, потому что в квайнах не принято читать файлы. Хорошо, а что если назвать файл print(__file__)
, записать в него print(__file__)
и выполнить python "print(__file__)"
. Будет работать, но можешь вот без этих трюков, чисто кодом? Да без проблем!
Нам нужно что-то печатать, значит берем print:
>>> print('?') ?
Программа начинается с print…, значит и печатать будем тоже самое:
>>> print('print()') print()
Не получается, потому что у нас тут уже два print да кавычки, а печатается только один. Так можно плодить print до бесконечности, но все равно не будет хватать одного в выводе. Будем решать поэтапно. Давайте заведем переменную s с кодом нашей программы.
>>> s='print()';print(s) print()
Но код теперь начинается с s=, исправим:
>>> s='s=?;print(s)';print(s) s=?;print(s)
Смотрите, уже похоже, осталось только на место знака вопроса воткнуть содержимое строки s из оригинального кода. Это самый важный момент. Используем format, а точнее s.format(s), который в определенном месте строки s вставит саму же строку s, таким образом, мы «разрываем рекурсию»:
>>> s='s={};print(s)';print(s.format(s)) s=s={};print(s);print(s)
Отлично! Но тут два недостатка: во-первых, не забыть добавить s.format(s)
в саму строку s:
>>> s='s={};print(s.format(s))';print(s.format(s)) s=s={};print(s.format(s));print(s.format(s))
Во-вторых, нужно вернуть на место кавычки. Не зря я недавно рассказывал о флагах преобразования строк. Используем флаг {!r}
в формате, чтобы вывести repr(s)
, который для строк содержит одинарные кавычки:
>>> s='s={!r};print(s.format(s))';print(s.format(s)) s='s={!r};print(s.format(s))';print(s.format(s))
Ура! Квайн готов и работает!
Вы можете сделать квайн короче, используя другой стиль форматирования строк через процент: {!r}
заменяется на %r
, s.format(s)
на s%s
, плюс экранируется процент внутри самой строки s%%s
(%% понимается как сам знак процента, а не как место для подстановки):
>>> s='s=%r;print(s%%s)';print(s%s) s='s=%r;print(s%%s)';print(s%s)
🐉 Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈