TGViewer
Находки в опенсорсе Находки в опенсорсе @opensource_findings · 12.6K subscribers
Post #856 5.51K
Лучший курс по Python 10: ==

44 минуты про сравнения, что может быть лучше?

https://www.youtube.com/watch?v=o-Ng_73kdik

В видео будет про:
- Сравнения в Python2 и усиление типизации в Python3
- Оптимизация байткода в Tier1: COMPARE_OP превращается в COMPARE_OP_{INT,STR,FLOAT}
- Разницу байткода и перформанса между a == b == c и a == b and b == c
- PyObject_RichCompare C-API
- Работу с NotImplemented
- Дефолтную реализацию object.__eq__, object.__lt__ и других

И даже за 44 минуты я не успел рассказать все! Делюсь дополнительными материалами здесь.

1. В ролике был вопрос: почему перед опкодом TO_BOOL идет дополнительный COPY? Ответ будет такой. Как выглядит опредление опкода TO_BOOL? op(_TO_BOOL, (value -- res)). Теперь, давайте разбираться, что такое (value -- res). bytecodes.c написан на специальном DSL, который упрощает определение работы с байткодом для разных уровней оптимизаторов, а так же делает работу со стеком виртуальной машины похожей на "вызов функций". (value -- res) значит: возьми со стека value, положи на стек res


op(_TO_BOOL, (value -- res)) {
int err = PyObject_IsTrue(PyStackRef_AsPyObjectBorrow(value));
DECREF_INPUTS();
ERROR_IF(err < 0, error);
res = err ? PyStackRef_True : PyStackRef_False;
}


Следовательно, если у нас не будет COPY:


pure inst(COPY, (bottom, unused[oparg-1] -- bottom, unused[oparg-1], top)) {
assert(oparg > 0);
top = PyStackRef_DUP(bottom);
}


То, мы для превращения объекта в bool в TO_BOOL возьмем со стека value, превратим его в bool, сложим на стек результат, его проверит POP_JUMP_IF_FALSE. А самого значения уже не останется. COPY позволяет сохранить само значение объекта в стеке, для дальнейшей работы с ним.

Документация: https://github.com/python/cpython/blob/main/Tools/cases_generator/interpreter_definition.md

2. Я не показал long_compare. Исправляюсь:


static Py_ssize_t
long_compare(PyLongObject *a, PyLongObject *b)
{
if (_PyLong_BothAreCompact(a, b)) {
return _PyLong_CompactValue(a) - _PyLong_CompactValue(b);
}
Py_ssize_t sign = _PyLong_SignedDigitCount(a) - _PyLong_SignedDigitCount(b);
if (sign == 0) {
Py_ssize_t i = _PyLong_DigitCount(a);
sdigit diff = 0;
while (--i >= 0) {
diff = (sdigit) a->long_value.ob_digit[i] - (sdigit) b->long_value.ob_digit[i];
if (diff) {
break;
}
}
sign = _PyLong_IsNegative(a) ? -diff : diff;
}
return sign;
}


Исходник: https://github.com/python/cpython/blob/656b7a3c83c79f99beac950b59c47575562ea729/Objects/longobject.c#L3548-L3567

Код кажется очевидным. Теперь полный цикл сравнений пройден :)

Вопрос для обсуждения: a == b == c или a == b and b == c? Какой стиль вы выбираете у себя?

Поддержать такой контент можно тут:
- https://boosty.to/sobolevn
- https://github.com/sponsors/wemake-services
YouTube Лучший курс по Python 10: == Лучший курс по питону: 10 Или "обзор исходников CPython с CPython core разработчиком". Тема: сравнения - Разница между == и is в Python - Как работают сравнения в Python? ==, != и другие - Зачем нужен NotImplemented в Python и в сравнениях? - Стандартные…
  • 🔥 38
  • ❤ 17
  • 👍 7
  • 😱 5
More from @opensource_findings
  1. Sep 28, 2026Еще анонсы докладов на бесплатную конференцию 17 октября в НН Регистрация: https://itgorky…
  2. Sep 25, 2026Монадические выражения в Python. Наконец-то! Продолжаем разговор про интересные PEPы. Пого…
  3. Sep 15, 2026PEPы в Python окончательно вышли из-под контроля Давайте посмотрим, что происходит с ПЕПам…
  4. Sep 10, 2026Большая бесплатная конференция в Нижнем Новгороде 17 октября Регистрация: https://itgorky.…
  5. Sep 1, 2026Post #985
  6. Aug 24, 2026JIT могут удалить из CPython! PEP-836: https://peps.python.org/pep-0836 JIT в CPython имее…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →