Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Rust 型別對應到 Python 型別

撰寫可由 Python 呼叫的函式(例如 #[pyfunction]#[pymethods] 區塊)時,函式引數需要 FromPyObject 特徵,回傳值需要 IntoPyObject 特徵。

請參考下一節的表格,找出 PyO3 提供且實作這些特徵的 Rust 型別。

引數型別

接受函式引數時,可以使用 Rust 程式庫型別或 PyO3 的 Python 原生型別。(何時使用哪種型別,請見下一節。)

下表列出 Python 型別及其對應可接受的函式引數型別:

PythonRustRust(Python 原生)
object-PyAny
strString, Cow<str>, &str, char, OsString, PathBuf, PathPyString
bytesVec<u8>, &[u8], Cow<[u8]>PyBytes
boolboolPyBool
inti8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize, num_bigint::BigInt1, num_bigint::BigUint1PyInt
floatf32, f64, ordered_float::NotNan2, ordered_float::OrderedFloat2PyFloat
complexnum_complex::Complex3PyComplex
fractions.Fractionnum_rational::Ratio4-
list[T]Vec<T>PyList
dict[K, V]HashMap<K, V>, BTreeMap<K, V>, hashbrown::HashMap<K, V>5, indexmap::IndexMap<K, V>6PyDict
tuple[T, U](T, U), Vec<T>PyTuple
set[T]HashSet<T>, BTreeSet<T>, hashbrown::HashSet<T>5PySet
frozenset[T]HashSet<T>, BTreeSet<T>, hashbrown::HashSet<T>5PyFrozenSet
bytearrayVec<u8>, Cow<[u8]>PyByteArray
slice-PySlice
type-PyType
module-PyModule
collections.abc.Buffer-PyBuffer<T>
datetime.datetimeSystemTime, chrono::DateTime<Tz>7, chrono::NaiveDateTime7PyDateTime
datetime.datechrono::NaiveDate7PyDate
datetime.timechrono::NaiveTime7PyTime
datetime.tzinfochrono::FixedOffset7, chrono::Utc7, chrono_tz::TimeZone8PyTzInfo
datetime.timedeltaDuration, chrono::Duration7PyDelta
decimal.Decimalrust_decimal::Decimal9-
decimal.Decimalbigdecimal::BigDecimal10-
ipaddress.IPv4Addressstd::net::IpAddr, std::net::Ipv4Addr-
ipaddress.IPv6Addressstd::net::IpAddr, std::net::Ipv6Addr-
os.PathLikePathBuf, PathPyString
pathlib.PathPathBuf, PathPyString
typing.Optional[T]Option<T>-
typing.Sequence[T]Vec<T>PySequence
typing.Mapping[K, V]HashMap<K, V>, BTreeMap<K, V>, hashbrown::HashMap<K, V>5, indexmap::IndexMap<K, V>6&PyMapping
typing.Iterator[Any]-PyIterator
typing.Union[...]See #[derive(FromPyObject)]-

另外也值得記住以下特殊型別:

項目說明
Python<'py>用來證明已附加到 Python 直譯器的 token。
Bound<'py, T>具有生命週期的 Python 物件,將其綁定到 Python 直譯器的附加狀態。可存取大多數 PyO3 API。
Py<T>不連結任何直譯器附加生命週期的 Python 物件,可傳送至其他執行緒。
PyRef<T>不可變借用的 #[pyclass]
PyRefMut<T>可變借用的 #[pyclass]

更多關於將 #[pyclass] 作為函式引數的細節,請見本指南的Python 類別章節

使用 Rust 程式庫型別 vs Python 原生型別

使用 Rust 函式庫型別作為函式引數,相較於 Python 原生型別會產生轉換成本。使用 Python 原生型別幾乎是零成本(只需進行類似 Python 內建函式 isinstance() 的型別檢查)。

不過,一旦付出轉換成本,Rust 標準函式庫型別會帶來多項好處:

  • 你可以用原生速度的 Rust 程式碼實作功能(不受 Python 執行期成本影響)。
  • 可與 Rust 生態系的其他元件有更好的互通性。
  • 你可使用 Python::detach 從直譯器分離,讓其他 Python 執行緒在 Rust 程式碼執行時繼續前進。
  • 你也會受益於更嚴格的型別檢查。例如指定 Vec<i32>,只會接受包含整數的 Python list。相對的 Python 原生等價型別 &PyList 會接受包含任何型別 Python 物件的 list

對於多數 PyO3 使用情境,付出轉換成本以換取上述好處是值得的。一如往常,若不確定是否值得,請進行基準測試!

將 Rust 值回傳給 Python

當從可由 Python 呼叫的函式回傳值時,可零成本使用 PyO3 的智慧指標Py<T>Bound<'py, T>Borrowed<'a, 'py, T>)。

由於 Bound<'py, T>Borrowed<'a, 'py, T> 具有生命週期參數,Rust 編譯器可能會要求你在函式中補上生命週期標註。請參考指南中專門章節

若函式可能失敗,應回傳 PyResult<T>Result<T, E>,其中 E 需實作 From<E> for PyErr。若回傳 Err 變體,將拋出 Python 例外。

最後,以下 Rust 型別也可作為回傳值轉換為 Python:

Rust 型別對應的 Python 型別
Stringstr
&strstr
boolbool
Any integer type (i32, u32, usize, etc)int
f32, f64float
Option<T>Optional[T]
(T, U)Tuple[T, U]
Vec<T>List[T]
Cow<[u8]>bytes
HashMap<K, V>Dict[K, V]
BTreeMap<K, V>Dict[K, V]
HashSet<T>Set[T]
BTreeSet<T>Set[T]
Py<T>T
Bound<T>T
PyRef<T: PyClass>T
PyRefMut<T: PyClass>T

  1. 需要 num-bigint 選用功能。 ↩2

  2. 需要 ordered-float 選用功能。 ↩2

  3. 需要 num-complex 選用功能。

  4. 需要 num-rational 選用功能。

  5. 需要 hashbrown 選用功能。 ↩2 ↩3 ↩4

  6. 需要 indexmap 選用功能。 ↩2

  7. 需要 chrono(以及可能的 chrono-local)選用功能。 ↩2 ↩3 ↩4 ↩5 ↩6 ↩7

  8. 需要 chrono-tz 選用功能。

  9. 需要 rust_decimal 選用功能。

  10. 需要 bigdecimal 選用功能。