Интересные развлечения со змеей
На этот раз у нас известный язык программирования Python, c двумя стилизованными змеями на логотипе, интересные и необычные развлечения с которым были собраны в этой замечательной статье.
Python — весьма занятный язык программирования с богатой историей, который сильно недооценивают многие серьезные программисты, напрасно полагая, что это «какие-то скрипты» для детей ML-щиков и тестировщиц.
Надеюсь описанное ниже даст определенное понимание, что «змеиный язык» сильно сложнее чем кажется и несет в себе множество нетривиальных нюансов.
Отказ от ответственности
Сам автор (несмотря на название статьи) всячески разделяет традиционные программистские ценности:
читаемость кода, адекватность реализации и радость применения
Поэтому заранее предупреждает, что попытка использовать описанные практики в реальном проекте может привести к серьезным проблемам со здоровьем и дальнейшим трудоустройством.
Возможно с вами даже перестанут здороваться за руку. Когда отвяжут от батареи.
Развлечение первое: Змея и Си
Декабрьским вечером 2020 года, на известном интернет-ресурсе, в группе по программированию появился вот такой невинный пост:
Вчера начал изучать Python и пока мне все нравится.
Хотя я давно пишу на С, некоторые вещи в Python уже кажутся проще чем в С.
А ведь еще есть множество практик, которые легко перенести из С! Очень нравится, что тут есть циклыwhileиforпрямо как в С. Боялся что придется опять все изучать с нуля, но оказалось что это не так. Единственное к чему пришлось привыкать, что выражения заканчиваются запятой а не точкой с запятой.
Как бы то ни было, вот мой скрипт (на Python 3.8, это всего лишь игрушечный скрипт для тестов циклов for и while). Есть идеи как можно улучшить мой код и сделать его более читаемым?
Каждый открывший этот код по ссылке, если он хоть немного понимал в программировании на Python — немедленно получал солнечный удар, разрыв мозга или сердечный приступ.
И острое желание сжечь диплом инженера, поскольку этот замечательный код ставил под сомнение границы реальности компетенции практически любого Python-разработчика.
Вот он целиком, сохранен для потомков:
#include <stdint.h>
#include <stdio.h>
#/* pre-declare types and functions */
void: (type) = (type) ("(void *)0"),
int16_t: (type) = (type) (int(16))(),
int32_t: (type) = (type) (int(32))(),
puts: ((str) := void) = (print),
printf: ((str) := void) = (puts),
#/* confirm function and variable declarations */
[[void]] = (void),
[[total]] = (int32_t),
[[i]] = (int32_t),
[[puts]] = (puts),
[[printf]] = (printf),
#/* ensure forwards and backwards compatibility */
import __future__ as __past__
#define FUTURE PAST
#define PAST FUTURE
#/* output a formatted string to stdout */
def printf(s, __VA_ARGS__) -> (void) :{
(void) (puts((void).__mod__(s, __VA_ARGS__), end=((void).__new__)(void))),
}
#/*******************************************************
# * SUMMATION SCRIPT *
# *******************************************************
# * Sum up all the natural numbers up to 6. The result *
# * should be 0 + 1 + 2 + 3 + 4 + 5 + 6 = 21. *
# *******************************************************/
#/* print numbers from 0 to 6 */
int32_t: i = 0,
while (i <= 6) :{
(void) (printf(" %d\n", i)),
(i := i + 1),
}
(void) (puts("__")),
#/* sum up numbers from 0 to 6 */
int32_t: total = 0,
int32_t: i = 0,
for (int32_t) in (i <- 0, i <= 6, ++i) :{
(total := total + i),
}
(void) (printf("%d\n", total)),Перед вами полностью рабочий код на языке Python, не на С.
К сожалению синтаксис успел немного поменяться с 2020го и попытка запуска на современной версии Python выдаст ошибку:
python довольно давно и повсеместно означает по-умолчанию 3.х версию, конкретно в этом случае - 3.11.Ошибку тем не менее легко исправить, убрав скобки вокруг str в двух строках. Было:
puts: ((str) := void) = (print), printf: ((str) := void) = (puts),
puts: (str := void) = (print), printf: (str := void) = (puts),
После правки все отлично запускается:
Теперь стоит рассказать как это чудовище инженерной мысли вообще работает, на случай если встретите подобное в темной подворотне реальном проекте.
Оригинальный разбор был также опубликован на Реддите, ниже приведен вольный перевод самых интересных фрагментов.
Начнем с банального, но далеко не всем очевидного:
#include <stdint.h> #include <stdio.h>
Строки выше — валидные инструкции препроцессора для языка С, но для Python они являются лишь текстовыми комментариями. Так что это чистый троллинг «змеелюбов» и строки выше никак не используются в логике программы.
Следующая интересная конструкция уже сильно сложнее для понимания:
void: (type) = (type) ("(void *)0"),Тут происходит объявление переменной с именем void и значением в виде типа строки, но поскольку в конце стоит запятая — на самом деле получается кортеж.
Вот такой хитрый финт ушами, хотя далеко не последний:
int16_t: (type) = (type) (int(16))(), int32_t: (type) = (type) (int(32))(),
Да это снова «троллинг-пародия» под код С, вызова int32_t = int() было бы достаточно. Но автор решил преобразовать 16 в int, получить тип, а затем вызвать его конструктор, что дало пустое значение этого типа.
Вызов int() даёт 0, если кто не знает.
puts: ((str) := void) = (print), printf: ((str) := void) = (puts),
Эти две строчки идентичны, так что вся конструкция просто задаёт функцию с именем puts, которая равна print, и printf, которая также равна print.
#/* confirm function and variable declarations */ [[void]] = (void), [[total]] = (int32_t), [[i]] = (int32_t), [[puts]] = (puts), [[printf]] = (printf),
Все строки выше на самом деле кортежи (из-за запятой в конце), а сама конструкция разворачивает их на уровень выше — становится возможным обратиться к переменной по имени в двойных квадратных скобках:
Следующие интересные строки являются чистым, стопроцентным троллингом:
#/* ensure forwards and backwards compatibility */ import __future__ as __past__ #define FUTURE PAST #define PAST FUTURE
Несмотря на то что в языке Python действительно присутствует специальная конструкция:
from __future__ import feature
указывающая компилятору на использование конструкций языка, которые еще не вошли в релизную версию, конечно же никаких «ensure forwards and backwards compatibility» нет и быть не может.
О чем и шутят пользователи Реддита, ссылаясь на «путешествия во времени»:
Следующий интересный блок, точно достойный разбора:
#/* output a formatted string to stdout */
def printf(s, __VA_ARGS__) -> (void) :{
(void) (puts((void).__mod__(s, __VA_ARGS__), end=((void).__new__)(void))),
}Тут переопределяется printf в виде функции, которая по идее должна возвращать строку из-за -> (void), но на самом деле возвращает None.
Поскольку такая конструкция проходит проверку типов, функция вида:
def x() -> str: return None
вполне имеет право на существование и вернет тип NoneType при вызове.
Еще из интересного тут происходит вызов метода __mod__ у"%d\n".
Следующий мозговыносящий для питонистов блок:
#/* print numbers from 0 to 6 */ int32_t: i = 0,
Тут создается новая переменная int32_t, у которой в качестве типа стоит i. Поскольку i был распакован конструкцией выше — все это проходит проверку типов и int32_t становится равно кортежу (0,).
while (i <= 6) :{
(void) (printf(" %d\n", i)),
(i := i + 1),
}Напоминаю, что это все еще стандартный Python, это не C и не Java.
Фигурные скобки тут на самом деле лишь для красоты ввода в заблуждение, поскольку будет работать и так:
def func(self): {
print("Yo braces!")
}def func(self):
print("Yo braces!") Теперь вы знаете чем выбесить порадовать интервьюера на собеседовании.
Но вернемся к примеру с циклом.
Перед нами стандартный цикл while, в котором за каждый проход создается набор (set) из двух элементов. Первый элемент это результат вызова str(print( %d\n"%i)), второй — счетчик с именем i.
После завершения цикла, у i будет значение 7.
Следующий блок кода, несмотря на внешнюю фантастичность, довольно простой:
(void) (puts("__")),Это аналог вызова str (print (__)). , который просто печатает на экране символ _. И все.
int32_t: i = 0,
for (int32_t) in (i <- 0, i <= 6, ++i) :{
(total := total + i),
}Да, это все еще обычный Python, без DSL и модулей расширения.
В примере выше создается кортеж вида (False, False, 7), поскольку 7 больше нуля, не меньше или равно 6 а вызов ++7 дает 7. Так что вся конструкция на самом деле аналогична привычному for _ in range(3):
Внутри цикла происходит увеличение значения переменной total на 7, 3×7 = 21, цикл отрабатывает три раза, создает три набора (set), которые равны значению total.
(void) (printf("%d\n", total)),Сия адская конструкция, будто бы прямиком из больного сознания старого LISP-программиста всего лишь.. выводит на экран значение переменной total.
Работа безусловно «мощи великой», но это еще не конец.
Развлечение второе: Змея-оборотень
Следующим интересным примером избытка свободного времени серьезных инженерных талантов является вот такой gist, c воодушевляющим названием evil.py.c.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define __file__ __FILE__
#define import void*
#define def int
import codecs;
import os;
import subprocess;
import tempfile;
#if PYTHON
LANG = 'Python'
FROM_C = globals().get('FROM_C', False)
START = None
END = None
PYTHON_CODE = lambda x: eval(compile('if 1:\n%s' % x[2:-3], '<string>', 'exec'),
globals(), globals())
C_CODE = lambda *args: None
PRINT_PREFIX, PRINT_SUFFIX = ('printf("', '\\n");') if FROM_C else ('', '')
write = lambda s, *args: print('%s%s%s' % (PRINT_PREFIX, s % args, PRINT_SUFFIX))
#else
# define LANG "C"
# define START int main() {
# define END }
# define PYTHON_CODE(x)
# define C_CODE(a, b, c) b
# ifdef FROM_PYTHON
# define PRINT_PREFIX "print(\"\"\""
# define PRINT_SUFFIX "\"\"\")"
#else
# define PRINT_PREFIX
# define PRINT_SUFFIX
#endif
# define write(x, ...) printf(PRINT_PREFIX x PRINT_SUFFIX "\n", __VA_ARGS__)
#endif
START
PYTHON_CODE((""" "
if FROM_C:
print("#include <stdio.h>")
print("int main() {");
" """))
write("%s: %s: Hello, world!", LANG, __file__);
PYTHON_CODE((""" "
def decode_c(text):
fd, out_file = tempfile.mkstemp()
os.close(fd)
try:
subprocess.check_output([
'clang', '-x', 'c',
'-DFROM_PYTHON=1',
__file__, '-o', out_file,
])
result = subprocess.check_output(out_file)
return result, len(result)
finally:
os.unlink(out_file)
if FROM_C:
print("}");
else:
codecs.register(lambda name: codecs.CodecInfo(lambda text: "",
decode_c,
name='c'))
exec(codecs.decode(open(__file__, 'r'), encoding='c'))
" """))
C_CODE(""" ",
#if !FROM_PYTHON
fflush(stdout);
popen("python3.8 -c \"FROM_C=True ; __file__ = '" __FILE__ "'; "
"exec(open('" __FILE__ "').read())\""
"| clang -x c -o .generated-evil -",
"r");
system("./.generated-evil");
unlink(".generated-evil");
#endif
," """)
ENDНесмотря на устрашающее название, ничего действительно злого этот код не делает, так что можете отключать антивирусы.
I regret nothing.
И я его не виню, поскольку перед нами отличный пример программы-оборотня, код которой валиден сразу для двух очень разных языков: Python и С.
Так выглядит запуск в виде скрипта Python:
А это уже компиляция с помощью clang в виде кода на С:
если вы чего-то понимаете в Python или С — могли заметить, что код выше несколько сложноват для простого вывода строки «Hello, world!»
Даже с учетом специфики «программы с двойным дном», исходного кода все равно многовато, а еще и в описании есть загадочная строка:
Так что код выше на самом деле выполняет два разных действия:
- действительно печатает «Hello, world!»;
- генерирует код для второй части, компилирует и тут же запускает.
Поэтому в выводе видны две строчки «Hello, world!» вместо одной, вторая — от запуска новой копии.
Добавлю, что в коде есть вот такое место:
popen("python3.8 -c \"FROM_C=True ; __file__ = '" __FILE__ "'; "
"exec(open('" __FILE__ "').read())\""
"| clang -x c -o .generated-evil -",
"r");Тут вшита версия Python, актуальная на момент создания проекта, но скорее всего в вашей системе не будет устаревшего Python 3.8, поэтому скрипт при попытке запуска упадет с ошибкой.
Для исправления либо замените в этом месте python3.8 на просто python3, либо создайте символьную ссылку с нужным именем:
ln -s /usr/bin/python3 ~/.local/bin/python3.8
Вот такой интересный проект, clang вызываемый через пайплайн автор до него не встречал.
Развлечение третье: Кошмар аудитора
На этот раз постарался известный LinkedIn, подбросив мне в вентилятор ленту замечательный пост с весьма необычным кодом:
Удивительно, но код снова полностью рабочий и запускается на современной версии Python (3.13) без каких-либо правок:
Привожу исходный код c картинки выше, дабы было проще копировать и рассылать знакомым змеелюбам питонистам:
def artifact():
def f(x): return x+1
def gate(x):
if x == 7:
f.__code__ = (lambda y: f"Ω:{y*y}").__code__
return f(x)
return gate
g = artifact()
print(g(1),g(7),g(2))То что тут происходит станет неприятным сюрпризом для всех, кто вынужден заниматься аудитом «змеиного кода»:
In Python, every function has an attribute called__code__.
This is the bytecode, the actual execution engine of the function.
And it can be replaced while the program is running.
По условию x == 7 происходит подмена байткода функции на лету — прямо в работающем приложении:
if x == 7:
f.__code__ = (lambda y: f"Ω:{y*y}").__code__Разумеется в самой технике нет ничего нового, аналогичный функционал присутствует и в Java и в C#, но только крестьянская простота с которой это происходит в Python определенно станет сюрпризом.
Заметить и отследить такое в реальном проекте весьма непросто.
Развлечение четвертое: Новый взгляд на ООП
Посмотрите на этот замечательный код, взятый из блога очередного бородатого эксперта, проведшего (судя по профилю на Github) много лет в интересных развлечениях со змеей:
class A:
def func(self):
print("A")
class B:
def func(self):
print("B")
a = A()
a.func() # A
a.__class__ = B
a.func() # BВ коде выше декларируются два разных, никак не связанных между собой класса:
нет общего предка и нет наследования.
Затем вызывается конструктор первого класса и получается экземпляр объекта, у которого затем вызывается тестовый метод — стандартные шаги, не вызывающие вопросов.
Но вот дальше происходит «чудо чудесное»:
a.__class__ = B
Перезаписывается специальный атрибут __class__ , в качестве значения устанавливается класс B, никак не связанный с A.
Затем происходит вызов метода func, чья сигнатура полностью совпадает в обоих классах.Да, это замечательно работает в Python, причем без каких-либо предупреждений:
Пикантности ситуации добавляет отсутствие явного вызова конструктора у класса B — представляете как весело такое ловить в реальном проекте?
Развлечение пятое: Змея и побитовый сдвиг
Самое интересное и шикарное я приберег на конец повествования, в качестве награды выжившим дочитавшим до этого места.
Итак, перед вами совершенно особенный код на Python, на котором карьеру программиста можно спокойно завершать:
(lambda _, __, ___, ____, _____, ______, _______, ________:
getattr(
__import__(True.__class__.__name__[_] + [].__class__.__name__[__]),
().__class__.__eq__.__class__.__name__[:__] +
().__iter__().__class__.__name__[_:][_____:________]
)(
_, (lambda _, __, ___: _(_, __, ___))(
lambda _, __, ___:
bytes([___ % __]) + _(_, __, ___ // __) if ___ else
(lambda: _).__code__.co_lnotab,
_ << ________,
(((_____ << ____) + _) << ((___ << _____) - ___)) + (((((___ << __)
- _) << ___) + _) << ((_____ << ____) + (_ << _))) + (((_______ <<
__) - _) << (((((_ << ___) + _)) << ___) + (_ << _))) + (((_______
<< ___) + _) << ((_ << ______) + _)) + (((_______ << ____) - _) <<
((_______ << ___))) + (((_ << ____) - _) << ((((___ << __) + _) <<
__) - _)) - (_______ << ((((___ << __) - _) << __) + _)) + (_______
<< (((((_ << ___) + _)) << __))) - ((((((_ << ___) + _)) << __) +
_) << ((((___ << __) + _) << _))) + (((_______ << __) - _) <<
(((((_ << ___) + _)) << _))) + (((___ << ___) + _) << ((_____ <<
_))) + (_____ << ______) + (_ << ___)
)
)
)(
*(lambda _, __, ___: _(_, __, ___))(
(lambda _, __, ___:
[__(___[(lambda: _).__code__.co_nlocals])] +
_(_, __, ___[(lambda _: _).__code__.co_nlocals:]) if ___ else []
),
lambda _: _.__code__.co_argcount,
(
lambda _: _,
lambda _, __: _,
lambda _, __, ___: _,
lambda _, __, ___, ____: _,
lambda _, __, ___, ____, _____: _,
lambda _, __, ___, ____, _____, ______: _,
lambda _, __, ___, ____, _____, ______, _______: _,
lambda _, __, ___, ____, _____, ______, _______, ________: _
)
)
)если сможете что-то подобное написать — заканчивайте с программированием, круче уже не будет.
Конечно же такая работа не могла появиться случайно, а ее автор — мягко говоря не новичок в программировании.
Работа заняла первое место в конкурсе для особенных по обфускации:
got first place in this Code Golf contest to create the weirdest obfuscated program that prints the string “Hello world!”
Оригинальный код был создан еще в далеком 2014м году, для совсем забытого ныне Python 2.7. Много позже — в 2017м автор опубликовал обновленную версию для Python 3.x, которую я и запустил в современном окружении:
Несмотря на острое желание, все же не стану пересказывать тут шаги реализации этого шедевра, дабы статья не превратилась в эпическую сагу о подвигах предков — в оригинальном посте все подробно описано.
Ограничусь лишь таким интересным скриншотом, демонстрирующим в работе одну из ключевых стадий создания:
Конечно мало шансов увидеть подобное в реальном приложении (что радует), если только вы не занимаетесь изучением малвари. Но даже в этом случае, столь сильно обфусцированный код на Python — большая редкость.
Еще больше диких змей
Помимо описанных выше чудес, в сети еще есть много подборок дичи, связанной с особенностями языка Python. Но поскольку статья не резиновая, ниже буквально одной строкой описываю самое интересное.
Python's horror show
https://github.com/pablogsal/python-horror-show
Содержит коллекцию примеров «змеиного кода» с подозрительным или нетривиальным поведением, с описанием причин:
Strange and odd python snippets explained
Некоторые примеры определенно заставят икать даже опытных разработчиков:
>>> all([]) True >>> all([[]]) False >>> all([[[]]]) True
WTF Python!
https://github.com/satwikkansal/wtfpython
Монументальная подборка отборной дичи, переведенная на 6 (шесть) языков:
Here's a fun project attempting to explain what exactly is happening under the hood for some counter-intuitive snippets and lesser-known features in Python.
Это точно стоит держать в закладках, особенно если заставляют разгребать код на Python за нейросетью с горящими сроками.
Ну и в качестве «дембельского аккорда» показываю самое лютое:
International Obfuscated Python Code Competition
Отдельный конкурс, целиком посвященный обфускации кода на Python — прямой аналог классического IOCCC!
В качестве примера одна из работ-победителей:
"""ᐌ([ᐊ(ᐄ(ᐆ('print',ᐇ()),[ᐄ(ᐈ(ᐄ(ᐆ('open',ᐇ()), [ᐆ('__file__ ',ᐇ()),ᐃ('r'
)],ᐉ),'read',ᐇ()),ᐉ,ᐉ)],ᐉ)),ᐊ(ᐄ(ᐆ('print',ᐇ()),ᐉ,ᐉ)), ᐂ([ᐁ('conte' 'xtlib'),ᐁ(
'io'),ᐁ('operator'),ᐁ('time')]),Assign([ᐆ('f',ᐋ())],ᐄ(ᐈ( ᐆ('io',ᐇ()), 'StringIO',ᐇ
()),ᐉ,ᐉ)),With([withitem(ᐄ(ᐈ(ᐆ('contextlib',ᐇ()),'redirect' '_stdout',ᐇ( )),[ᐆ('f',ᐇ(
))],ᐉ))],[ᐂ( [ᐁ('this')])]) ,For(Tuple([ ᐆ('i',ᐋ()),ᐆ
('l',ᐋ())],ᐋ ()),ᐄ(ᐆ('enum' 'erate',ᐇ()) ,[ᐄ(ᐈ(ᐄ(ᐈ(ᐆ(
'f',ᐇ()),'g' 'etvalue',ᐇ()) ,ᐉ,ᐉ),'spli' 'tlines',ᐇ()
),ᐉ,ᐉ)],ᐉ),[ ᐎ(ᐒ(ᐏ(),ᐆ('i' ,ᐇ())),[ᐊ(ᐄ( ᐆ('print',ᐇ(
)),[ᐓ([ᐃ('H' 'ow does this' ' code do i' 'n terms of'
' >'),ᐑ(ᐄ(ᐈ( ᐆ('l',ᐇ()),'r' 'eplace',ᐇ() ),[ᐃ(','),ᐃ(
'<')],ᐉ),-1) ,ᐃ('?')])],ᐉ)) ,ᐐ()],[ᐎ(ᐒ(ᐏ (),ᐆ('l',ᐇ()
)),[ᐊ(ᐄ(ᐆ('' 'print',ᐇ()),ᐉ, ᐉ)),ᐐ()],ᐉ)] ),ᐊ(ᐄ(ᐆ('pr'
'int',ᐇ()),[ ᐍ(ᐅ(ᐆ('comment' ,ᐋ( )),ᐄ( ᐈ( Dict([ᐃ(11),
ᐃ(12),ᐃ(13), ᐃ(17),ᐃ(19)],[ᐃ( 'no errors were silenced'
),ᐃ('no err' 'ors were thrown'),ᐃ( 'everything is crystal'
' clear'),ᐃ('for this code, never would have been better') ,ᐃ('does not apply')]
),'get',ᐇ()),[ᐆ('i',ᐇ())],ᐉ)),ᐄ(ᐈ(ᐓ([ᐃ('\x1b[32m✔ '),ᐑ (ᐆ('l',ᐇ()),-1),ᐃ(
'\x1b[0m__#_'),ᐑ(ᐆ('comment',ᐇ()),-1),ᐃ('.')]),'re' 'place',ᐇ()),[ᐃ(
'_'),ᐃ(' ')],ᐉ),ᐓ([ᐃ('\x1b[91m✘ '),ᐑ(ᐆ('l',ᐇ()) ,-1)]))],ᐉ)),
ᐊ(ᐄ(ᐈ(ᐆ('time',ᐇ()),'sleep',ᐇ()),[ᐃ(0.3)],ᐉ ))],ᐉ),ᐊ(ᐄ(ᐆ
('print',ᐇ() ),[ᐃ('\x1b['
'0m')],ᐉ)),ᐊ (ᐄ(ᐆ('print'
,ᐇ()),[ᐃ('W' 'ell...')],ᐉ
) ),ᐊ(ᐄ(ᐈ(ᐆ( 'time',ᐇ()),
'sleep',ᐇ()) ,[ᐃ(3)],ᐉ)),
ᐊ(ᐄ(ᐆ('prin' 't',ᐇ()),[ᐃ(
'I tried.')] ,ᐉ))],ᐉ)""";
...;from ast import *;ᐁ,\
ᐂ,ᐃ,ᐅ,ᐄ,ᐆ,ᐈ, ᐇ,ᐌ,ᐉ,ᐋ,ᐊ,ᐍ\
,ᐐ, ᐎ,ᐏ,ᐒ,ᐓ, ᐑ = alias ,\
Import , Constant ,\
NamedExpr , Call, Name,\
Attribute , Load,Module\
,[], Store , Expr,IfExp,\
Continue,If, Not,UnaryOp\
,JoinedStr , FormattedValue
exec(unparse (fix_missing_locations
(eval(__doc__ ))))#Johannes LippmannКод выше, несмотря на всю дикость для глаз обычного питониста абсолютно и полностью рабочий:
Вот такой он Python — необычный язык программирования, названный в честь известного шоу Monty Python и с двумя змеями на логотипе.