日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
結(jié)合使用Python和Rust

Python 和 Rust 是非常不同的語言,但它們實際上非常搭配。但在討論如何將 Python 與 Rust 結(jié)合之前,我想先介紹一下 Rust 本身。你可能已經(jīng)聽說了這種語言,但可能還沒有了解過它的細節(jié)。

什么是 Rust?

Rust 是一種低級語言,這意味著程序員所處理的東西接近于計算機的 “真實” 運行方式。

例如,整數(shù)類型由字節(jié)大小定義,與 CPU 支持的類型相對應。雖然我們很想簡單地說 Rust 中的 a+b 對應于一條機器指令,但實際上并不完全是這樣!

Rust 編譯器鏈非常復雜。作為第一種近似的方法,將這樣的語句視為 “有點” 真實是有用的。

Rust 旨在實現(xiàn)零成本抽象,這意味著許多語言級別可用的抽象在運行時環(huán)境中會被編譯去掉。

例如,除非明確要求,對象會在堆棧上分配。結(jié)果是,在 Rust 中創(chuàng)建本地對象沒有運行時成本(盡管可能需要進行初始化)。

最后,Rust 是一種內(nèi)存安全的語言。也有其他內(nèi)存安全的語言和其他支持零成本抽象的語言。但通常這些是兩類不同的語言。

內(nèi)存安全并不意味著不可能在 Rust 中出現(xiàn)內(nèi)存違規(guī)。它確實意味著只有兩種方式可能導致內(nèi)存違規(guī):

  • 編譯器的錯誤。
  • 顯式聲明為不安全(unsafe)的代碼。

Rust 標準庫代碼有很多被標記為不安全的代碼,雖然比許多人預期的少。這并不意味著該語句無意義。除了需要自己編寫不安全代碼的(罕見的)情況外,內(nèi)存違規(guī)通常是由基礎(chǔ)設(shè)施造成的。

為什么會有 Rust 出現(xiàn)?

為什么人們要創(chuàng)建 Rust?是哪些問題沒有被現(xiàn)有編程語言解決嗎?

Rust 被設(shè)計成既能高效運行,又保證內(nèi)存安全。在現(xiàn)代的聯(lián)網(wǎng)世界中,這是一個越來越重要的問題。

Rust 的典型應用場景是協(xié)議的低級解析。待解析的數(shù)據(jù)通常來自不受信任的來源,并且需要通過高效的方式進行解析。

如果你認為這聽起來像 Web 瀏覽器所做的事情,那不是巧合。Rust 最初起源于 Mozilla 基金會,它是為了改進 Firefox 瀏覽器而設(shè)計的。

如今,需要保證安全和速度的不僅僅是瀏覽器。即使是常見的微服務架構(gòu)也必須能夠快速解析不受信任的數(shù)據(jù),同時保證安全。

現(xiàn)實示例:統(tǒng)計字符

為了理解 “封裝 Rust” 的例子,需要解決一個問題。這個問題需要滿足以下要求:

  • 足夠容易解決。
  • 能夠?qū)懜咝阅苎h(huán)來優(yōu)化。
  • 有一定的現(xiàn)實意義。

這個玩具問題的例子是判斷一個字符在一個字符串中是否出現(xiàn)超過了 X 次。這個問題不容易通過高效的正則表達式解決。即使是專門的 Numpy 代碼也可能不夠快,因為通常沒有必要掃描整個字符串。

你可以想象一些 Python 庫和技巧的組合來解決這個問題。然而,如果在低級別的語言中實現(xiàn)直接的算法,它會非??欤⑶腋子陂喿x。

為了使問題稍微有趣一些,以演示 Rust 的一些有趣部分,這個問題增加了一些變化。該算法支持在換行符處重置計數(shù)(意即:字符是否在一行中出現(xiàn)了超過 X 次?)或在空格處重置計數(shù)(意即:字符是否在單詞中出現(xiàn)了超過 X 次?)。

這是唯一與 “現(xiàn)實性” 相關(guān)的部分。過多的現(xiàn)實性將使這個示例在教育上不再有用。

支持枚舉

Rust 支持使用枚舉(enum)。你可以使用枚舉做很多有趣的事情。

目前,只使用了一個簡單的三選一的枚舉,并沒有其他的變形。這個枚舉編碼了哪種字符重置計數(shù)。

#[derive(Copy)]
enum Reset {
    NewlinesReset,
    SpacesReset,
    NoReset,
}

支持結(jié)構(gòu)

接下來的 Rust 組件更大一些:這是一個結(jié)構(gòu)(struct)。Rust 的結(jié)構(gòu)與 Python 的 dataclass 有些相似。同樣,你可以用結(jié)構(gòu)做更復雜的事情。

#[pyclass]
struct Counter {
    what: char,
    min_number: u64,
    reset: Reset, 
}

實現(xiàn)塊

你可以在 Rust 中使用一個單獨的塊,稱為實現(xiàn)(impl)塊,為結(jié)構(gòu)添加一個方法。但具體細節(jié)超出了本文的范圍。

在這個示例中,該方法調(diào)用了一個外部函數(shù)。這主要是為了分解代碼。更復雜的用例將指示 Rust 編譯器內(nèi)聯(lián)該函數(shù),以便在不產(chǎn)生任何運行時成本的情況下提高可讀性。

#[pymethods]
impl Counter {
    #[new]
    fn new(what: char, min_number: u64, reset: Reset) -> Self {
        Counter{what: what, min_number: min_number, reset: reset}
    }
    fn has_count(
        &self,
        data: &str,
    ) -> bool {
        has_count(self, data.chars())
    }
}

函數(shù)

默認情況下,Rust 變量是常量。由于當前的計數(shù)(current_count)必須更改,因此它被聲明為可變變量。

fn has_count(cntr: &Counter, chars: std::str::Chars) -> bool {
    let mut current_count : u64 = 0;
    for c in chars {
        if got_count(cntr, c, &mut current_count) {
            return true;
        }
    }
    false
}

該循環(huán)遍歷字符并調(diào)用 got_count 函數(shù)。再次強調(diào),這是為了將代碼分解成幻燈片展示。它展示了如何向函數(shù)發(fā)送可變引用。

盡管 current_count 是可變的,但發(fā)送和接收站點都顯式標記該引用為可變。這可以清楚地表明哪些函數(shù)可能修改一個值。

計數(shù)

got_count 函數(shù)重置計數(shù)器,將其遞增,然后檢查它。Rust 的冒號分隔的表達式序列評估最后一個表達式的結(jié)果,即是否達到了指定的閾值。

fn got_count(cntr: &Counter, c: char, current_count: &mut u64) -> bool {
    maybe_reset(cntr, c, current_count);
    maybe_incr(cntr, c, current_count);
    *current_count >= cntr.min_number
}

重置代碼

reset 的代碼展示了 Rust 中另一個有用的功能:模式匹配。對 Rust 中匹配的完整描述需要一個學期級別的課程,不適合在一個無關(guān)的演講中講解。這個示例匹配了該元組的兩個選項之一。

fn maybe_reset(cntr: &Counter, c: char, current_count: &mut u64) -> () {
    match (c, cntr.reset) {
        ('\n', Reset::NewlinesReset) | (' ', Reset::SpacesReset)=> {
            *current_count = 0;
        }
        _ => {}
    };
}

增量支持

增量將字符與所需字符進行比較,并在匹配時增加計數(shù)。

fn maybe_incr(cntr: &Counter, c: char, current_count: &mut u64) -> (){
    if c == cntr.what {
        *current_count += 1;
    };
}

請注意,我在本文中優(yōu)化了代碼以適合幻燈片。這不一定是 Rust 代碼的最佳實踐示例,也不是如何設(shè)計良好的 API 的示例。

為 Python 封裝 Rust 代碼

為了將 Rust 代碼封裝到 Python 中,你可以使用 PyO3。PyO3 Rust “crate”(即庫)允許內(nèi)聯(lián)提示將 Rust 代碼包裝為 Python,使得修改兩者更容易。

包含 PyO3 crate 原語

首先,你必須包含 PyO3 crate 原語。

use pyo3::prelude::*;

封裝枚舉

枚舉需要被封裝。derive 從句對于將枚舉封裝為 PyO3 是必需的,因為它們允許類被復制和克隆,使它們更容易在 Python 中使用。

#[pyclass]
#[derive(Clone)]
#[derive(Copy)]
enum Reset {
    /* ... */
}

封裝結(jié)構(gòu)

結(jié)構(gòu)同樣需要被封裝。在 Rust 中,這些被稱為 “宏”,它們會生成所需的接口位。

#[pyclass]
struct Counter {
    /* ... */
}

封裝實現(xiàn)

封裝實現(xiàn)(impl)更有趣。增加了另一個名為 new 的宏。此方法被標記為 #[new],讓 PyO3 知道如何為內(nèi)置對象公開構(gòu)造函數(shù)。

#[pymethods]
impl Counter {
    #[new]
    fn new(what: char, min_number: u64,
          reset: Reset) -> Self {
        Counter{what: what,
          min_number: min_number, reset: reset}
    }
    /* ... */
}

定義模塊

最后,定義一個初始化模塊的函數(shù)。此函數(shù)具有特定的簽名,必須與模塊同名,并用 #[pymodule] 修飾。

#[pymodule]
fn counter(_py: Python, m: &PyModule
) -> PyResult<()> {
    m.add_class::()?;
    m.add_class::()?;
    Ok(())
}

? 顯示此函數(shù)可能失?。ɡ?,如果類沒有正確配置)。 PyResult 在導入時轉(zhuǎn)換為 Python 異常。

Maturin 開發(fā)

為了快速檢查,用 maturin develop 構(gòu)建并將庫安裝到當前虛擬環(huán)境中。這有助于快速迭代。

$ maturin develop

Maturin 構(gòu)建

maturin build 命令構(gòu)建一個 manylinux 輪子,它可以上傳到 PyPI。輪子是特定于 CPU 架構(gòu)的。

Python 庫

從 Python 中使用庫是最簡單的部分。沒有任何東西表明這與在 Python 中編寫代碼有什么區(qū)別。這其中的一個有用方面是,如果你優(yōu)化了已經(jīng)有單元測試的 Python 中的現(xiàn)有庫,你可以使用 Python 單元測試來測試 Rust 庫。

導入

無論你是使用 maturin develop 還是 pip install 來安裝它,導入庫都是使用 import 完成的。

import counter

構(gòu)造函數(shù)

構(gòu)造函數(shù)的定義正好使對象可以從 Python 構(gòu)建。這并不總是如此。有時僅從更復雜的函數(shù)返回對象。

cntr = counter.Counter(
    'c',
    3,
    counter.Reset.NewlinesReset,
)

調(diào)用函數(shù)

最終的收益終于來了。檢查這個字符串是否至少有三個 “c” 字符:

>>> cntr.has_count("hello-c-c-c-goodbye")
True

添加一個換行符會觸發(fā)剩余操作,這里沒有插入換行符的三個 “c” 字符:

>>> cntr.has_count("hello-c-c-\nc-goodbye")
False

使用 Rust 和 Python 很容易

我的目標是讓你相信將 Rust 和 Python 結(jié)合起來很簡單。我編寫了一些“粘合劑”代碼。Rust 和 Python 具有互補的優(yōu)點和缺點。

Rust 非常適合高性能、安全的代碼。Rust 具有陡峭的學習曲線,對于快速原型解決方案而言可能有些笨拙。

Python 很容易入手,并支持非常緊密的迭代循環(huán)。Python 確實有一個“速度上限”。超過一定程度后,從 Python 中獲得更好的性能就更難了。

將它們結(jié)合起來完美無縫。在 Python 中進行原型設(shè)計,并將性能瓶頸移至 Rust 中。

使用 Maturin,你的開發(fā)和部署流程更容易進行。開發(fā)、構(gòu)建并享受這一組合吧!


新聞名稱:結(jié)合使用Python和Rust
網(wǎng)站網(wǎng)址:http://www.dlmjj.cn/article/dhpjdog.html