TGViewer
P(hD)ython P(hD)ython @phdython · 333 subscribers
Post #35 416
«Python для собесов - 2026 🚀»

#python

На днях я понял, что хоть мой канал и называется P(hD)ython, на нём всё ещё нет ни одного полноценного поста про Python 😅.

Исправим это! Запускаю серию постов, которые помогут Вам при прохождении Python-собеседований в 2026 году 😎.

Один из моих любимых вопросов на Python-собесах звучит так: «если все ругают Python за скорость, то почему на нём пишут столько ML и математики?!». Удивительно, но часто на нём сыплются даже матёрые разработчики.

Отвечаю! Сам по себе Python и правда медленный (почему - отдельный вопрос), но когда дело доходит до тяжёлых вычислений, оказывается, что он вызывает функции, написанные на компилируемых языках вроде Rust, C\C++ или... Fortran!

Так, например, numpy по сути является обёрткой над С-массивами, а scipy.linalg.lapack обычно импортирует Fortran-библиотеку LAPACK! Даже pytorch, исполняясь на GPU, по факту делает это на C\C++ & CUDA ⚙️.

Всё это достигается за счёт Foreign Function Interface (FFI) - механизма, позволяющего коду на одном языке вызывать функции, написанные на другом. FFI есть не только в Python. Он имеется в Rust (extern "C" & unsafe), Java (JNI & JNA), Go (cgo) и т.д., так что идея этого поста легко обобщается и на другие языки.

А теперь пример! Сегодня мы напишем свой собственный numpy с поэлементным умножением float-векторов!

Сперва реализуем функцию fmul поэлементного умножения float-векторов на C в файле fmul.c:

#include <stddef.h>
void fmul(const float* a, const float* b, float* out, size_t n) {
for (size_t i = 0; i < n; ++i) out[i] = a[i] * b[i];
}


Скомпилируем его как разделяемую библиотеку:

gcc -O3 -fPIC -shared -o libfmul.so fmul.c


Установим cffi для поддержки FFI в Python:

pip install cffi


Теперь напишем Python-класс для работы с float-векторами и fmul в файле fmul.py:

from array import array
from pathlib import Path
from cffi import FFI

# через FFI подгружаем разделяемую библиотеку в Python-код
ffi = FFI()
ffi.cdef("void fmul(const float* a,const float* b,float* out,size_t n);")
C = ffi.dlopen(str(Path(__file__).with_name("libfmul.so")))

class F32Vec:
# используем __slots__ для более компактного и производительного представления объектов класса
__slots__ = ("a",)

# требуем, чтобы наш класс конструировался из float-массива Python
def __init__(self, data):
self.a = (
data
if isinstance(data, array) and data.typecode == "f"
else array("f", data)
)

def __len__(self):
return len(self.a)

def _mul_arr(self, other):
if len(self.a) != len(other):
raise ValueError("len mismatch")

# готовим выходной массив
out = array("f", [0.0]) * len(self.a)

# вызываем через FFI C-функцию fmul
C.fmul(
ffi.from_buffer("float[]", self.a),
ffi.from_buffer("float[]", other),
ffi.from_buffer("float[]", out),
len(self.a),
)
return F32Vec(out)

# перегружаем операторы умножения, чтобы поэлементное произведение работало как в numpy
def __mul__(self, other):
if isinstance(other, F32Vec):
return self._mul_arr(other.a)
if isinstance(other, (int, float)):
return self._mul_arr(array("f", [float(other)]) * len(self.a))
return self._mul_arr(array("f", other))

__rmul__ = __mul__

def tolist(self):
return list(self.a)

def __repr__(self):
return f"F32Vec({list(self.a)})"


if __name__ == "__main__":
x = F32Vec([0.0, 0.5, 1.0, 1.5])
y = F32Vec([1.0, 2.0, 3.0, 4.0])

print(x._mul_arr(y.a))
print((x * y).tolist())
print((x * 2.0))
print((2.0 * x).tolist())


Наконец, запустим код:

python3 fmul.py
F32Vec([0.0, 1.0, 3.0, 6.0])
[0.0, 1.0, 3.0, 6.0]
F32Vec([0.0, 1.0, 2.0, 3.0])
[0.0, 1.0, 2.0, 3.0]


Сегодня мы узнали, почему медленный Python способен быстро перемножать вектора, и как работает FFI! К сожалению, FFI громоздок и требует знания других языков. Как этого избежать - поговорим в следующем посте 🚀!

С уважением,
Михаил Масягин
  • ❤ 14
  • 🔥 10
  • 🏆 5
  • ✍ 1
More from @phdython
  1. Aug 25, 2026«Конференции и паровозики 🚂» #заметки_с_полей Отгремела «Профсоюзная 2.0» - конфа прошла…
  2. Aug 22, 2026Post #81
  3. Aug 20, 2026«Профсоюз выдвинул 😎» #заметки_с_полей 22 августа в Москве буду спикером на «Профсоюзной…
  4. Aug 16, 2026«Ну вот, я и стал админом 🧑‍💻» #техно_и_хардкор Собрал, казалось бы, банальный, но для м…
  5. Aug 11, 2026«Предзащита: больно и неофициально 🎓» #аспирантские_будни Наконец дошли руки до обещанног…
  6. Jul 18, 2026«Work-life balance от Anthropic ⚒️» #ai4sdlc Недельные лимиты токенов израсходованы - можн…
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 →