IlmHamroh
Python kursi/Python va boshqa tillar10/16-dars18 daqiqa
Mundarija (22)

30.10-dars: PyO3 — Rust moduli

30-QISM — PYTHON VA BOSHQA TILLAR · 10-dars


1. Kirish va motivatsiya

Rust nega Python uchun jozibali ekanini 30.9-bob ko'rdik: C tezligi + xotira xavfsizligi. Endi ularni birlashtiramiz — Rust'da yozilgan funksiyani Python'dan chaqiriladigan qilamiz. Bu PyO3 kutubxonasi bilan bo'ladi: Rust funksiyasiga #[pyfunction] deb belgi (atribut) qo'yasiz, modulga #[pymodule] — PyO3 qolganini avtomatik qiladi (Python obyektlariga o'girish, C API — 30.5, hammasi yashirin). C kengaytmasi 30.6-bob qanchalik qiyin bo'lsa (PyObject, havolalar, funksiya jadvallari qo'lda), PyO3 shunchalik oson: Rust yozasiz, #[pyfunction] qo'yasiz, tayyor. PyO3 — Rust va Python o'rtasidagi zamonaviy, qulay ko'prik. polars, pydantic-core shu bilan qurilgan.

PyO3 — Rust va Python o'rtasida bog'lovchi kutubxona: #[pyfunction] (Rust funksiyani Python'ga ochish — atribut/dekorator), #[pymodule] (Rust modulini Python moduliga), avtomatik o'girish (Rust turlari ↔ Python obyektlari — C API 30.5 yashirin), #[pyclass] (Rust struct'ni Python klass'ga). Foydalanish: tez+xavfsiz kengaytma (Rust yadro), Python interfeys. Bu 30.9 (Rust — nega), 30.6 (C kengaytma — qiyin muqobil) bilan bog'liq. Bu 30.9 (Rust), 30.11 (maturin — yig'ish) bilan bog'liq. PyO3 — Rust'ni Python'ga. Atributlar. Oson.

Real vaziyat. Bir jamoa masofa hisobinit (koordinatalar — million juftlik, CPU-og'ir 29.2) tezlashtirmoqchi edi. Rust tanlandi (30.9 — tez+xavfsiz). PyO3 bilan: Rust'da masofa(a, b) funksiyasi yozildi, ustiga #[pyfunction] qo'yildi, modulga #[pymodule]. PyO3 qolganini avtomatik qildi (Python float ↔ Rust f64, C API yashirin). Python'dan import geo; geo.masofa(...) — oddiy. C kengaytma (30.6 — PyObject, havola qo'lda) bo'lsa, o'nlab qator murakkab kod kerak edi; PyO3 bilan bir atribut. PyO3 — Rust kengaytma, minimal murakkablik.

Bu darsda PyO3 bilan Rust modulini o'rganamiz.

Bu darsda:

  • PyO3 nima
  • #[pyfunction] — funksiyani ochish
  • #[pymodule] — modul
  • Avtomatik tur o'girish
  • #[pyclass] — Rust klass
  • PyO3 amaliyoti
  • PyO3 vs C kengaytma
  • Amaliy: PyO3 modeli

ℹ PyO3 Rust/kompilyator talab qiladi; misollar PyO3 struktura mantiqini (deterministik) modellashtiradi.


2. Nazariya — chuqur tushuntirish

2.1. PyO3 nima

Rust'ni Python'ga bog'lash:

rust
// mening_modul (Rust — PyO3 bilan)
use pyo3::prelude::*;

#[pyfunction]                          // Python'ga ochish
fn qoshish(a: i64, b: i64) -> i64 {
    a + b                              // Rust (tez + xavfsiz)
}

#[pymodule]                            // Python moduli
fn mening_modul(m: &Bound<PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(qoshish, m)?)?;
    Ok(())
}

PyO3 — Rust va Python o'rtasida bog'lovchi kutubxona: Rust kodini Python'dan import qilinadigan qiladi, minimal kod bilan (atributlar — #[pyfunction], #[pymodule]). Sabab: C kengaytma 30.6-bob qiyin (PyObject, havola, jadval qo'lda — C API 30.5); PyO3 buni avtomatlashtiradi (Rust yozasiz, atribut qo'yasiz, PyO3 C API'ni yaratadi — yashirin). Bu Cython (30.7 — Python'ga C tezlik) ning Rust ekvivalenti (Rust'ga Python interfeys). PyO3 tez (Rust 30.9) + xavfsiz + oson (atribut). polars, pydantic-core PyO3 bilan. PyO3 — Rust'ni Python'ga. Atributlar. Oson ko'prik.

2.2. #[pyfunction] — funksiyani ochish

Rust funksiyani Python'ga:

rust
#[pyfunction]                          // bu atribut — Python'ga ochadi
fn kvadrat(x: f64) -> f64 {
    x * x
}
// Python'da: modul.kvadrat(3.0) → 9.0
// PyO3 avtomatik: Python float ↔ Rust f64

#[pyfunction] — PyO3'ning asosiy atributi: Rust funksiyasini Python'ga ochadi (Python'dan chaqiriladigan). Sabab: oddiy Rust funksiya Python'dan ko'rinmaydi; #[pyfunction] atributi PyO3'ga "bu funksiya Python'ga chiqsin" deydi (PyO3 kerakli C API kodini avtomatik yaratadi — argument o'girish, natija o'girish). Bu C kengaytmadagi PyMethodDef (30.6 — funksiya jadvali qo'lda) ning avtomatik ekvivalenti (atribut bir qator). Foydalanish: har Python'ga kerakli Rust funksiyaga #[pyfunction]. #[pyfunction] — funksiyani ochish (atribut). Avtomatik C API. PyMethodDef ekvivalenti.

2.3. #[pymodule] — modul

Rust modulini Python moduliga:

rust
#[pymodule]                            // Python moduli
fn geo(m: &Bound<PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(masofa, m)?)?;   // funksiya qo'shish
    m.add_function(wrap_pyfunction!(burchak, m)?)?;
    Ok(())
}
// Python'da: import geo; geo.masofa(...)

#[pymodule] — PyO3 modul atributi: Rust funksiyasini Python moduliga aylantiradi (funksiyalarni ro'yxatlaydi). Sabab: Python modul kerak (import geo); #[pymodule] funksiyasi modulni ta'riflaydi — m.add_function bilan har #[pyfunction] ni qo'shadi (Python'ga ko'rinadigan). Bu C kengaytmadagi PyModuleDef + PyInit (30.6 — modul + init qo'lda) ning avtomatik ekvivalenti. Modul nomi = funksiya nomi (geo). Foydalanish: bir #[pymodule], ichida funksiyalar qo'shiladi. #[pymodule] — modul (atribut). add_function. PyModuleDef ekvivalenti.

2.4. Avtomatik tur o'girish

PyO3 turlarni o'zi o'giradi:

Rust turi          ↔  Python turi
   i64, i32         ↔  int
   f64              ↔  float
   String, &str     ↔  str
   Vec<T>           ↔  list
   HashMap<K,V>     ↔  dict
   bool             ↔  bool

PyO3 avtomatik o'giradi (dasturchi qo'lda emas)

Avtomatik tur o'girish — PyO3'ning kuchli qulayligi: Rust turlarini Python turlariga (va aksincha) avtomatik o'giradi — i64↔int, f64↔float, String↔str, Vec↔list, HashMap↔dict. Sabab: C API'da 30.5-bob turlar qo'lda o'giriladi (PyLong_AsLong, PyLong_FromLong — 30.5); PyO3 buni avtomatik qiladi (Rust tur tizimi bilan — #[pyfunction] imzosi turlarni biladi). Bu C kengaytma (30.6 — qo'lda o'girish) dan keskin osonroq (avtomatik). Cheklov: murakkab tur (maxsus struct) uchun #[pyclass] 2.5-bob. Avtomatik o'girish — Rust ↔ Python turlar. Qo'lda emas. C API yashirin.

2.5. #[pyclass] — Rust klass

Rust struct'ni Python klass'ga:

rust
#[pyclass]                             // Python klass
struct Nuqta {
    #[pyo3(get, set)]                  // Python'dan o'qish/yozish
    x: f64,
    #[pyo3(get, set)]
    y: f64,
}

#[pymethods]                           // klass metodlari
impl Nuqta {
    #[new]                             // konstruktor
    fn new(x: f64, y: f64) -> Self {
        Nuqta { x, y }
    }
}
// Python'da: n = Nuqta(1.0, 2.0); n.x

#[pyclass] — Rust struct'ni Python klass'ga aylantirish: #[pyclass] (struct → klass), #[pyo3(get, set)] (maydon — Python'dan o'qish/yozish), #[pymethods] (metodlar bloki), #[new] (konstruktor — __init__). Sabab: ba'zan funksiya yetmaydi — obyekt kerak (holat, metodlar — 16-qism OOP); #[pyclass] Rust struct'ni to'liq Python klass qiladi (Python'dan Nuqta(1, 2), n.x, n.usul()). Bu C API'da 30.5-bob juda qiyin (klass qo'lda — o'nlab qator); PyO3'da atributlar. Foydalanish: holat/metod kerak (klass), oddiy hisob (funksiya). #[pyclass] — Rust struct → Python klass. Atributlar. OOP.

2.6. PyO3 amaliyoti

PyO3 amaliyotlari: #[pyfunction] (funksiya — Python'ga); #[pymodule] (modul — funksiyalar qo'sh); avtomatik tur (Rust ↔ Python — qo'lda emas); #[pyclass] (obyekt kerak — struct → klass); maturin (30.11 — yig'ish, .whl); xato boshqarish (PyResult — Rust xatosi → Python istisno); ownership (30.9 — Rust qoidalari, PyO3 bilan ham); bottleneck (29.2 — faqat sekin joy Rust). Tuzoqlar: Rust o'rganish (ownership — vaqt), ortiqcha (oddiy ishga — Cython 30.7 osonroq), tur mosligi (murakkab tur — #[pyclass]). Amaliyot — atributlar (pyfunction, pymodule, pyclass), avtomatik tur, maturin. PyO3 — Rust'ni Python'ga oson.

2.7. PyO3 vs C kengaytma

Jihat C kengaytma (30.6) PyO3 (Rust)
Til C (xavfli) Rust (xavfsiz)
Funksiya ochish PyMethodDef (qo'lda) #[pyfunction] (atribut)
Modul PyModuleDef+PyInit (qo'lda) #[pymodule] (atribut)
Tur o'girish Qo'lda (PyLong_...) Avtomatik
Havola INCREF/DECREF (qo'lda) Avtomatik (ownership)
Qiyinlik Yuqori O'rta (Rust o'rganish)

PyO3 vs C kengaytma: C kengaytma (30.6 — C til xavfli, PyMethodDef/PyModuleDef/PyInit qo'lda, tur o'girish qo'lda, havola INCREF/DECREF qo'lda — 30.5, ko'p murakkab kod); PyO3 (Rust — xavfsiz 30.9, atributlar #[pyfunction]/#[pymodule], tur o'girish avtomatik, havola avtomatik — Rust ownership; ancha kamroq kod, xavfsizroq). Sabab: PyO3 C API murakkabligini yashiradi (Rust + atribut), C kengaytma ochiq (qo'lda). Farq: PyO3 xavfsiz (Rust), oson (atribut), C kengaytma xavfli (C), qiyin (qo'lda). PyO3'da asosiy sarmoya — Rust o'rganish (ownership 30.9), lekin C API osonroq. PyO3 — Rust + atribut (oson, xavfsiz). C kengaytma — C + qo'lda. PyO3 afzal (zamonaviy).

2.8. PyO3 — Rust va Python zamonaviy ko'prigi

PyO3 asosiy g'oyasi — Rust va Python zamonaviy ko'prigi: Rust'ning tezlik va xavfsizligini 30.9-bob Python'ning qulayligi bilan atributlar orqali birlashtiradi (#[pyfunction], #[pymodule], #[pyclass] — PyO3 qolganini avtomatik). Bu C kengaytma (30.6 — C API qo'lda, qiyin, xavfli) ning zamonaviy, xavfsiz, oson muqobili. PyO3 C API murakkabligini (PyObject, havola, jadval — 30.5) yashiradi (Rust tur tizimi + atribut → avtomatik). Bu 30.1 (to'g'ri til to'g'ri ishga — Rust yadro + Python qobiq) ning zamonaviy amalga oshirilishi; polars, pydantic-core, tokenizers PyO3 bilan (tez + xavfsiz + oson). Rust o'rganish sarmoya (ownership), lekin natija kuchli (C tezlik, C xavfsizlik emas, oson interfeys). PyO3 — Rust ↔ Python (atribut). Zamonaviy ko'prik.


3. Tez ma'lumotnoma

rust
// PYO3 — Rust'ni Python'ga (mening_modul)
use pyo3::prelude::*;

// #[pyfunction] — funksiyani Python'ga ochish
#[pyfunction]
fn qoshish(a: i64, b: i64) -> i64 { a + b }

// #[pymodule] — Python moduli (funksiyalar qo'shish)
#[pymodule]
fn mening_modul(m: &Bound<PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(qoshish, m)?)?;
    Ok(())
}

// #[pyclass] — Rust struct → Python klass
#[pyclass]
struct Nuqta { #[pyo3(get, set)] x: f64, #[pyo3(get, set)] y: f64 }

#[pymethods]
impl Nuqta {
    #[new]
    fn new(x: f64, y: f64) -> Self { Nuqta { x, y } }
}
AVTOMATIK TUR O'GIRISH:
   i64/i32 ↔ int · f64 ↔ float · String/&str ↔ str
   Vec<T> ↔ list · HashMap ↔ dict · bool ↔ bool

PYO3 vs C KENGAYTMA:
   C — qo'lda (PyMethodDef, PyLong_..., INCREF) — xavfli
   PyO3 — atribut (#[pyfunction]), avtomatik tur — xavfsiz

QOIDA: atribut (pyfunction/pymodule/pyclass) + avtomatik tur + maturin (30.11)

PyO3 xulosasi

PyO3 — Rust'ni Python'ga bog'lash (atributlar bilan, oson)
#[pyfunction] — funksiyani ochish (PyMethodDef avtomatik)
#[pymodule] — Python moduli (funksiyalar qo'shish)
Avtomatik tur — Rust ↔ Python (qo'lda emas, C API yashirin)
#[pyclass] — Rust struct → Python klass (OOP) · maturin yig'adi

4. Batafsil misollar

PyO3 Rust/kompilyator talab qiladi; misollar PyO3 struktura mantiqini (deterministik) modellashtiradi.

Misol 1 — #[pyfunction] (atribut)

python
"""#[pyfunction]: Rust funksiyani Python'ga ochish (model)."""


def pyfunction_model(nom: str, rust_imzo: str) -> dict:
    return {
        "nom": nom,
        "rust_imzo": rust_imzo,
        "atribut": "#[pyfunction]",
        "python_korinish": True,
    }


def main() -> None:
    print("=== 1. Rust funksiya ===")
    f = pyfunction_model("kvadrat", "fn kvadrat(x: f64) -> f64")
    print(f"  {f['rust_imzo']}")

    print("\n=== 2. Atribut ===")
    print(f"  {f['atribut']} (Python'ga ochadi)")

    print("\n=== 3. Python'da ko'rinishi ===")
    print(f"  modul.{f['nom']}3.0-bob → 9.0")

    print("\n=== 4. C kengaytma farqi ===")
    print("  C: PyMethodDef qo'lda (jadval)")
    print("  PyO3: #[pyfunction] (bir atribut)")
    print("  ⭐ #[pyfunction] — funksiyani ochish (avtomatik)")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Rust funksiya ===
  fn kvadrat(x: f64) -> f64

=== 2. Atribut ===
  #[pyfunction] (Python'ga ochadi)

=== 3. Python'da ko'rinishi ===
  modul.kvadrat(3.0) → 9.0

=== 4. C kengaytma farqi ===
  C: PyMethodDef qo'lda (jadval)
  PyO3: #[pyfunction] (bir atribut)
  ⭐ #[pyfunction] — funksiyani ochish (avtomatik)

Nima ko'rsatdi: 2.1, 2.2-bo'limlar.

Misol 2 — Avtomatik tur o'girish

python
"""Avtomatik tur: Rust ↔ Python o'girish jadvali (model)."""


TUR_JADVAL = {
    "i64": "int",
    "f64": "float",
    "String": "str",
    "Vec<T>": "list",
    "HashMap<K,V>": "dict",
    "bool": "bool",
}


def main() -> None:
    print("=== 1. Tur o'girish jadvali ===")
    for rust, python in TUR_JADVAL.items():
        print(f"  {rust:14} ↔ {python}")

    print("\n=== 2. Avtomatik ===")
    print("  PyO3 o'zi o'giradi (dasturchi qo'lda emas)")

    print("\n=== 3. C API farqi 30.5-bob ===")
    print("  C: PyLong_AsLong / PyLong_FromLong (qo'lda)")
    print("  PyO3: imzodan avtomatik (Rust tur tizimi)")

    print("\n=== 4. Cheklov ===")
    print("  murakkab tur → #[pyclass]")
    print("  ⭐ Avtomatik tur — Rust ↔ Python (C API yashirin)")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Tur o'girish jadvali ===
  i64            ↔ int
  f64            ↔ float
  String         ↔ str
  Vec<T>         ↔ list
  HashMap<K,V>   ↔ dict
  bool           ↔ bool

=== 2. Avtomatik ===
  PyO3 o'zi o'giradi (dasturchi qo'lda emas)

=== 3. C API farqi 30.5-bob ===
  C: PyLong_AsLong / PyLong_FromLong (qo'lda)
  PyO3: imzodan avtomatik (Rust tur tizimi)

=== 4. Cheklov ===
  murakkab tur → #[pyclass]
  ⭐ Avtomatik tur — Rust ↔ Python (C API yashirin)

Nima ko'rsatdi: 2.4-bo'lim.

Misol 3 — #[pyclass] (Rust struct → klass)

python
"""#[pyclass]: Rust struct'ni Python klass'ga (model)."""


class PyclassModel:
    def __init__(self, struct_nomi: str, maydonlar: list) -> None:
        self.struct_nomi = struct_nomi
        self.maydonlar = maydonlar
        self.atributlar = ["#[pyclass]", "#[pymethods]", "#[new]"]


def main() -> None:
    n = PyclassModel("Nuqta", ["x: f64", "y: f64"])

    print("=== 1. Rust struct ===")
    print(f"  struct {n.struct_nomi} {{ {', '.join(n.maydonlar)} }}")

    print("\n=== 2. Atributlar ===")
    for a in n.atributlar:
        print(f"  {a}")

    print("\n=== 3. Python'da ===")
    print(f"  n = {n.struct_nomi}(1.0, 2.0)")
    print("  n.x  # get/set atributi")

    print("\n=== 4. OOP ===")
    print("  struct + metodlar → Python klass (holat)")
    print("  ⭐ #[pyclass] — Rust struct → Python klass")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Rust struct ===
  struct Nuqta { x: f64, y: f64 }

=== 2. Atributlar ===
  #[pyclass]
  #[pymethods]
  #[new]

=== 3. Python'da ===
  n = Nuqta(1.0, 2.0)
  n.x  # get/set atributi

=== 4. OOP ===
  struct + metodlar → Python klass (holat)
  ⭐ #[pyclass] — Rust struct → Python klass

Nima ko'rsatdi: 2.5-bo'lim.

Misol 4 — PyO3 vs C kengaytma (kod miqdori)

python
"""PyO3 vs C: bir funksiya uchun qadamlar soni (model)."""


def qadamlar(usul: str) -> dict:
    if usul == "C kengaytma":
        q = ["C funksiya", "PyArg_ParseTuple", "PyLong_FromLong",
             "PyMethodDef", "PyModuleDef", "PyInit", "INCREF/DECREF"]
    else:  # PyO3
        q = ["Rust funksiya", "#[pyfunction]", "#[pymodule] qo'shish"]
    return {"usul": usul, "qadamlar": q}


def main() -> None:
    print("=== 1. C kengaytma qadamlari ===")
    c = qadamlar("C kengaytma")
    for i, q in enumerate(c["qadamlar"], 1):
        print(f"  {i}. {q}")
    print(f"  jami: {len(c['qadamlar'])} qadam (qo'lda)")

    print("\n=== 2. PyO3 qadamlari ===")
    p = qadamlar("PyO3")
    for i, q in enumerate(p["qadamlar"], 1):
        print(f"  {i}. {q}")
    print(f"  jami: {len(p['qadamlar'])} qadam (atribut)")

    print("\n=== 3. Farq ===")
    print(f"  C: {len(c['qadamlar'])} qo'lda vs PyO3: {len(p['qadamlar'])} atribut")

    print("\n=== 4. Qo'shimcha ===")
    print("  PyO3 xavfsiz (Rust), C xavfli (qo'lda havola)")
    print("  ⭐ PyO3 — kamroq kod, xavfsizroq (atribut)")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. C kengaytma qadamlari ===
  1. C funksiya
  2. PyArg_ParseTuple
  3. PyLong_FromLong
  4. PyMethodDef
  5. PyModuleDef
  6. PyInit
  7. INCREF/DECREF
  jami: 7 qadam (qo'lda)

=== 2. PyO3 qadamlari ===
  1. Rust funksiya
  2. #[pyfunction]
  3. #[pymodule] qo'shish
  jami: 3 qadam (atribut)

=== 3. Farq ===
  C: 7 qo'lda vs PyO3: 3 atribut

=== 4. Qo'shimcha ===
  PyO3 xavfsiz (Rust), C xavfli (qo'lda havola)
  ⭐ PyO3 — kamroq kod, xavfsizroq (atribut)

Nima ko'rsatdi: 2.7-bo'lim.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"PyO3 = C kengaytma qiyinligi" PyO3 oson (atribut)
"Turlarni qo'lda o'gir" Avtomatik (Rust ↔ Python)
"#[pyfunction] keraksiz" Funksiyani Python'ga ochadi
"Havolani qo'lda hisobla" Avtomatik (Rust ownership)
"Faqat funksiya" #[pyclass] (klass ham)
"PyO3 xavfli (C kabi)" Rust xavfsiz (ownership)
"Rust o'rganishsiz" Ownership o'rganish kerak
"C API ko'rinadi" Yashirin (PyO3 avtomatik)

6. Keng tarqalgan xatolar va yechimlari

1. #[pyfunction] unutish

rust
fn qoshish(...) {...}   // atributsiz (Python ko'rmaydi)       // ⚠️
#[pyfunction] fn qoshish(...) {...}   // atribut               // ✅

2. #[pymodule]ga qo'shmaslik

rust
// #[pyfunction] bor, lekin modulga add_function yo'q          // ⚠️
m.add_function(wrap_pyfunction!(qoshish, m)?)?;                // ✅

3. Murakkab turga avtomatik kutish

rust
fn f(x: MaxsusStruct)   // avtomatik o'girmaydi                // ⚠️
#[pyclass] struct MaxsusStruct {...}   // pyclass              // ✅

4. Xatoni panic bilan (crash)

rust
fn f() { panic!(...) }   // Rust panic → crash                 // ⚠️
fn f() -> PyResult<...> { Err(...) }   // Python istisno       // ✅

5. Oddiy ishga PyO3 (ortiqcha)

python
# kichik tezlashtirishga Rust+PyO3 (o'rganish)                # ⚠️
# Cython 30.7-bob — osonroq, tez natija                          # ✅

6. maturinsiz yig'ish

python
# Rust kod bor, lekin .whl yo'q (yig'ilmagan)                 # ⚠️
# maturin 30.11-bob — yig'ish, .whl                              # ✅

7. get/set unutish (pyclass)

rust
#[pyclass] struct N { x: f64 }   // n.x ishlamaydi             // ⚠️
#[pyo3(get, set)] x: f64   // o'qish/yozish                    // ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 30.9-dars (o'tilgan): Rust — nega Python bilan
  • 30.11-dars: maturin — Rust yig'ish
  • 30.6-dars (o'tilgan): C kengaytma — qiyin muqobil
  • 30.7-dars (o'tilgan): Cython — oson muqobil
  • 30.5-dars (o'tilgan): C API — PyO3 yashiradi

8. Eng yaxshi amaliyotlar

  1. #[pyfunction] (funksiyani Python'ga ochish).

  2. #[pymodule]ga add_function (qo'shish).

  3. Avtomatik tur (Rust ↔ Python — qo'lda emas).

  4. #[pyclass] (obyekt/holat kerak).

  5. PyResult (xato — Python istisno, panic emas).

  6. maturin 30.11-bob — yig'ish, .whl.

  7. Bottleneck 29.2-bob Rust, qolgani Python.

  8. Oddiy ishga Cython (PyO3 — jiddiy/xavfsizlik).


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # PyO3 nima?
2.  # PyO3 nega oson?
3.  # #[pyfunction] nima?
4.  # #[pymodule] nima?
5.  # add_function nima?
6.  # avtomatik tur nima?
7.  # i64 ↔ ?
8.  # Vec<T> ↔ ?
9.  # #[pyclass] nima?
10. # #[new] nima?
11. # PyO3 vs C kengaytma?
12. # xato qanday?
Javoblar
  1. Rust'ni Python'ga bog'lash kutubxonasi
  2. Atributlar (PyO3 C API'ni avtomatik)
  3. Rust funksiyani Python'ga ochish (atribut)
  4. Rust modulini Python moduliga
  5. Funksiyani modulga qo'shish
  6. Rust ↔ Python turlar (avtomatik)
  7. int
  8. list
  9. Rust struct → Python klass
  10. Konstruktor (init)
  11. PyO3 atribut/avtomatik/xavfsiz, C qo'lda/xavfli
  12. PyResult (Err → Python istisno)

Vazifa 2: Xatolarni tuzating

python
1.  fn qoshish(...)   # atributsiz

2.  # modulga add_function yo'q

3.  fn f(x: MaxsusStruct)   # avtomatik kutish

4.  fn f() { panic!() }   # xato

5.  # kichik ishga PyO3
Javoblar
python
1.  #[pyfunction] fn qoshish(...)

2.  m.add_function(wrap_pyfunction!(...))

3.  #[pyclass] struct MaxsusStruct

4.  PyResult + Err (Python istisno)

5.  Cython (osonroq)

Vazifa 3: #[pyfunction]

Modellang:

  1. Rust funksiya
  2. Atribut
  3. Python ko'rinish
  4. C farqi

Vazifa 4: Avtomatik tur

Modellang:

  1. i64/int
  2. String/str
  3. Vec/list
  4. Avtomatik

Vazifa 5: #[pyclass]

Modellang:

  1. Struct
  2. Atributlar
  3. Konstruktor
  4. Python klass

Vazifa 6: PyO3 vs C

Modellang:

  1. C qadamlar
  2. PyO3 qadamlar
  3. Farq
  4. Xavfsizlik

Vazifa 7: O'ylash

PyO3 atributlar (#[pyfunction]) orqali murakkab C API kodini (PyObject, havolalar, jadvallar) yashiradi — dasturchi bir atribut yozadi, PyO3 o'nlab qatorni avtomatik yaratadi. Nima uchun "deklarativ" yondashuv (nima kerakligini aytish — #[pyfunction]) "imperativ" yondashuvdan (qanday qilishni yozish — C API qadamlari) ko'pincha yaxshiroq, va nega "atribut/dekorator" abstraksiyasi kuchli vosita?

Javob

Qisqa javob: "Deklarativ" yondashuv imperativdan ko'pincha yaxshiroq, chunki: deklarativ niyatni ifodalaydi ("bu funksiya Python'ga chiqsin" — #[pyfunction]), imperativ mexanizmni (qanday chiqarish — PyMethodDef, PyLong_..., INCREF, o'nlab qadam); niyat qisqa, aniq, o'qiladi (nima kerakligi ko'rinadi), mexanizm uzun, murakkab, xatoga moyil (qanday qilish yashiringan bo'lishi kerak). "Nega deklarativ yaxshiroq": (1) kamroq kod — #[pyfunction] (bir qator) vs C API (o'nlab qator); kamroq kod = kamroq xato, kamroq saqlash; (2) niyat ko'rinadi — #[pyfunction] o'qiganda "Python'ga ochiladi" darhol ravshan; C API'da niyat qadamlar ichida yo'qoladi (nima uchun bu INCREF?); (3) mexanizm yashirin — "qanday" (C API) PyO3 zimmasida (mutaxassis bir marta to'g'ri yozgan, hamma foydalanadi); dasturchi "nima"ga e'tibor beradi (biznes mantiq); (4) xato kamayadi — mexanizm (havola, jadval) yashirin → dasturchi xato qila olmaydi (PyO3 to'g'ri qiladi). "Nega atribut/dekorator kuchli": atribut — metama'lumot (kodga "belgi" qo'yish — bu funksiya maxsus); u kodni o'zgartirmasdan yangi xatti-harakat qo'shadi (PyO3 atributni ko'rib, kod yaratadi); bu ajratish (funksiya mantig'i alohida, Python'ga ochish alohida — atribut); qayta ishlatiladi (har funksiyaga bir xil atribut). Bu umumiy tamoyil: deklarativ (SQL — "nima kerak", nima qatorlar; HTML — "nima ko'rsatilsin"; Docker — "nima holat" 28.1) imperativdan (har qadamni yozish) ko'pincha ustun — niyat aniq, mexanizm yashirin, kamroq xato. Boshqa misollar: dekorator (@property, @staticmethod — 16-qism), type hint (x: int — niyat), routing (@app.route). Muhandislik saboqlari: niyatni ifodala (nima), mexanizmni yashir (qanday); deklarativ — qisqa, o'qiladi, kamroq xato; atribut/dekorator — metama'lumot (kodni o'zgartirmasdan xatti-harakat); ajratish (mantiq vs infratuzilma — atribut); mutaxassis mexanizmni bir marta (hamma foydalanadi). PyO3 misolida: #[pyfunction] niyat (Python'ga ochish); PyO3 mexanizm (C API) — dasturchi C API bilmasligi mumkin (niyatga e'tibor).

1. Nega deklarativ yaxshiroq

  • Niyatni ifodalaydi (nima kerak — #[pyfunction])
  • Kamroq kod (atribut vs o'nlab qator)
  • Niyat ko'rinadi (o'qiladi)
  • Mexanizm yashirin (xato kamayadi)

2. Nega atribut/dekorator kuchli

  • Metama'lumot (kodga belgi — maxsus)
  • Kodni o'zgartirmasdan xatti-harakat
  • Ajratish (mantiq alohida, ochish alohida)
  • Qayta ishlatiladi (bir xil atribut)

3. Deklarativ vs imperativ

Jihat Deklarativ (#[pyfunction]) Imperativ (C API)
Ifoda Niyat (nima) Mexanizm (qanday)
Uzunlik Qisqa Uzun
Xato Kam (yashirin) Ko'p (qo'lda)

4. Boshqa misollar

SQL (nima qatorlar), HTML (nima ko'rsatilsin), Docker (nima holat), dekorator (@property), type hint (x: int).

5. Muhandislik saboqlari

  1. Niyatni ifodala (nima), mexanizm yashir (qanday)
  2. Deklarativ — qisqa, o'qiladi, kamroq xato
  3. Atribut/dekorator — metama'lumot (xatti-harakat)
  4. Ajratish (mantiq vs infratuzilma)
  5. Mutaxassis mexanizmni bir marta

6. Xulosa

  1. Deklarativ — niyat (nima), imperativ — mexanizm (qanday)
  2. #[pyfunction] — niyat, PyO3 — mexanizm (yashirin)
  3. Atribut kuchli — metama'lumot (kodni o'zgartirmasdan)
  4. Kamroq kod, kamroq xato, o'qiladi

Nimani mustahkamlaydi: 2.1, 2.7-bo'limlar.


Xulosa

Bu darsda PyO3 bilan Rust modulini o'rgandik.

Eng muhim uch fikr:

  1. PyO3 va #[pyfunction]. PyO3 — Rust va Python o'rtasida bog'lovchi kutubxona: Rust kodini Python'dan import qilinadigan qiladi atributlar bilan (#[pyfunction], #[pymodule]), C API murakkabligini yashirib. #[pyfunction] — Rust funksiyasini Python'ga ochadi (atribut; PyO3 kerakli C API kodini avtomatik yaratadi — argument/natija o'girish); C kengaytmadagi PyMethodDef (30.6 — jadval qo'lda) ning avtomatik ekvivalenti. #[pymodule] — Rust modulini Python moduliga (m.add_function bilan funksiyalarni qo'shadi); PyModuleDef+PyInit avtomatik ekvivalenti.

  2. Avtomatik tur va #[pyclass]. Avtomatik tur o'girish — PyO3 Rust turlarini Python turlariga o'giradi (i64↔int, f64↔float, String↔str, Vec↔list, HashMap↔dict); C API'da 30.5-bob qo'lda (PyLong_...), PyO3'da avtomatik (Rust tur tizimi — imzodan). #[pyclass] — Rust struct'ni Python klass'ga (#[pyclass] struct→klass, #[pyo3(get, set)] maydon, #[pymethods] metodlar, #[new] konstruktor); obyekt/holat kerak bo'lsa (OOP). Havola ham avtomatik (Rust ownership — INCREF/DECREF qo'lda emas).

  3. C kengaytma taqqoslash va zamonaviy ko'prik. PyO3 vs C kengaytma: C (C til xavfli, PyMethodDef/PyModuleDef/PyInit qo'lda, tur/havola qo'lda — ko'p murakkab kod), PyO3 (Rust xavfsiz, atributlar, tur/havola avtomatik — kamroq kod, xavfsizroq); asosiy sarmoya Rust o'rganish (ownership 30.9), lekin C API osonroq. PyO3 — Rust va Python zamonaviy ko'prigi (tezlik+xavfsizlik+qulaylik, atribut orqali); C kengaytma 30.6-bob ning zamonaviy muqobili; polars, pydantic-core, tokenizers PyO3 bilan. Deklarativ atribut (#[pyfunction] — niyat) imperativ C API'dan (mexanizm — qadamlar) ustun (qisqa, o'qiladi, kamroq xato); atribut/dekorator — kuchli abstraksiya (metama'lumot, mantiq vs infratuzilma ajratiladi).

Keyingi darsda maturin bilan yig'ishni o'rganamiz: Rust+PyO3 kodini Python paketga (.whl) aylantirish — maturin develop/build, PyPI'ga chiqarish va foydalanuvchi Rust kompilyatorisiz o'rnatishi.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
30.10-dars: PyO3 — Rust moduli — IlmHamroh