Cython全教程2 多種定義方式

—— 本篇文章,主要講述Cython中的四種定義關鍵字

全教程2 多種定義方式:

? ? ? ? 在Cython中,關于定義的關鍵字有四個,分別是:

? ? ? ? cdefdefcpdefDEF

一、cdef定義關鍵字

? ? ? ? 顧名思義,cdef關鍵字定義的是一個C函數/方法(CFunction),也用來定義C變量

????????定義的東西只能Cython里調用而在Python里無法訪問到。

? ? ? ? 我相信,理解以下案例,即可掌握 (注意看代碼旁的注釋)

? ? ? ? (1)正確案例:

#cython: language_level=3
# -*- coding: UTF-8 -*-
# -*- file: test.pyx -*-###在Cython里: 可以單個定義變量/函數
cdef int cint_value1 = 66, cint_value2 = 88 #定義了兩個int變量
cdef float cfloat_value = 10.0              #定義了一個float變量
cdef float *h = &cfloat_value               #定義了一個float指針變量cdef int* cint_list = [1, 2, 3]            #定義數組①:使用指針聲明數組
cdef float[3] float_list1 = [1.0, 2.0]     #定義數組②:使用類Java聲明數組
cdef list[3] float_list2 = [6.0, 7.0, 8.0] #定義數組③:使用python列表
cdef double double_list[2] = [12.2, 13.3]  #定義數組④:使用類C聲明數組,不推薦cdef dict[int, str] dt = {}           #定義了一個字典,鍵為int,值為str。或者直接用dict也行cdef tuple tp = (1, 2, 3)
cdef tuple[3] tp = (1, 2, 3)
cdef tuple[int, int, int] _tp = (1, 2, 3)
cdef (int, int, int) __tp = (1, 2, 3) #上中下4種定義元組的方式都可以cdef tuple[list[3], dict[str, list[2]]] complex_tp  #定義復雜的也可以cdef void say_hello() noexcept: #聲明這個函數里沒有拋出錯誤print("Hello, Cython!")cdef int set_value(int* value) except *: #聲明這個函數里拋出了錯誤if value == NULL:                    #在C函數參數列表里無需使用cdefraise Exception("野指針!")value[0] = 100return value[0]    #Cython里指針只能用下標表示cdef void say_more_hello() noexcept:cdef int _for _ in range(10):say_hello() #調用say_hello()函數###或者一次性大量定義
cdef:double d_value = 0.0 #double型bint is_ok = 1       #1/0,類似于bool型(其實就是bool型)unsigned int u_int = 0signed int s_int = -1void is_ok_say():print("我學會了" if is_ok else "我再想想")#定義了一個C++類
cdef class CppClass(object):cdef:int cppclassdef __cinit__(CppClass self) -> None: #注意1:__cinit__其實就是__init__self.cppclass = 100               #注意2:self最好也寫上類型#注意3:Magic Method只能用def而不能用cdefcdef int get_cppclass(CppClass self) noexcept:return self.cppclasscdef object cppclass_plus1(CppClass self) noexcept: #C函數里也可以使用閉包cdef void inter_func():self.cppclass += 1return inter_func@staticmethodcdef void hello() noexcept:say_more_hello()@staticmethodcdef (int, int, int) get_tp() noexcept:return _tp

? ? ? ? 結合以上,注意:

? ? ? ? :在C++類(cdef class)里,聲明對象屬性只能在類體里,也就是在cdef int cppclass那里,并且不能直接在聲明的時候賦值(不能有默認值)。

? ? ? ? :在C++類(cdef class)里,魔法方法(特殊方法)不能使用cdef,只能使用def。

? ? ? ? :在C++類(cdef class)里,__cinit__方法類似于__init__方法,都屬于初始化方法。但不同的是,__cinit__適合于給對象屬性賦值,__init__適合調用函數/方法;__cinit__先于__init__執行(它們可以同時存在)。

? ? ? ? :定義的C變量/屬性,能用的類型不外乎于(int, float, bint, list, dict, tuple, 自己定義的C類型, Cython自帶的C類型),對于其他的類型,只能用object來聲明。

? ? ? ? :在C++類(cdef class)里,C++類的父類只能是C++類或object類或Exception類,C++類不允許繼承Py類。

? ? ? ? :對于C++類(cdef class),可以直接被Python訪問到,但其里面的C函數不能被訪問到

? ? ? ??(2)以下的是錯誤實例:

#cython: language_level=3
# -*- coding: UTF-8 -*-
# -*- file: test.pyx -*-cdef void* printf = print           #錯誤!只能用object來聲明指針函數,或者說,Py函數只能用object接受,C函數可以用指針函數接受
cdef tuple[int] tp1 = (1, 2, 3)     #錯誤!聲明的元組里面只能有一個int,即tuple[int]<->tuple[1]
cdef tuple tp2 = (1, 2, 3, 4, 5)    #正確!這樣的話可以
cdef tuple[5] tp3 = (1, 2, 3, 4, 5) #正確!這樣的話也可以from abc import ABC
cdef class CppClass(ABC): #錯誤!ABC為Py類,C++類只能僅能繼承C++類/object/Exceptioncdef __cinit__(CppClass self) noexcept: #錯誤!特殊方法只能是def定義self.cppclass = 100 #錯誤!必須先在類體內定義才能當作對象屬性使用def __repr__(CppClass self) -> str: #正確!特殊方法只能是def定義return ""

?(3)來個語境實例:

#cython: language_level=3
# -*- coding: UTF-8 -*-
# -*- file: test.pyx -*-#假設在D:/Test/test.pyx
cdef void say_hello() noexcept:print("Hello, Cython!")cdef class CppClass(object):def __cinit__(CppClass self) -> None:passcdef void say_more_hello1(CppClass self) noexcept:cdef int _for _ in range(10):say_hello()def say_more_hello2(CppClass self) -> None:cdef int _for _ in range(10):say_hello()#假設現在編譯了,在D:/Test/main.py
from test import *say_hello() #報錯!cdef定義的C函數只能在Cython里使用cpp: CppClass = CppClass() #允許!C++類直接可以在Python里使用cpp.say_more_hello1() #錯誤!cdef定義的C函數只能在Cython里使用,在Python里訪問不到
cpp.say_more_hello2() #正確!def定義的Py函數可以使用,可以訪問到

?(4)再舉個實際的實例:

#cython: language_level=3
# -*- coding: UTF-8 -*-
# -*- file: test.pyx -*-import pygame
import tkintercdef class PygameRun(object):cdef object screen  #注意看此處,Py類聲明的對象只能用object!cdef PygameRun run  #PgameRun是C++類,就是C類型,當然可以不用object了def __cinit__(PygameRun self) -> None:pygame.init()self.screen = pygame.display.set_mode((100, 100), RESIZABLE|SCALED, vsync=1)self.run = self...cdef object get_image(PygameRun self, str file) noexcept: #注意看此處,Py類聲明的對象只能用object!return pygame.image.load(file).convert_alpha()cdef PygameRun get_pygamerun(PygameRun self) noexcept: #PygameRun是C++類,就是C類型return self.runcdef object get_pygamescreen(PygameRun self) noexcept: #Py類聲明的對象就只能用object了return self.screencdef class TkinterRun(tkinter.Tk): #錯誤!C++類不能繼承Py類!pass

二、def定義關鍵字

? ? ? ? 就如在Python類似,def關鍵字是定義一個函數/方法(PyFunction),只不過在Cython里應該說為“定義一個Py函數/方法”。Py函數可以被Python調用,當然也能被Cython所調用。

????????但需要注意以下操作:

? ? ? ?:Py函數里不能完成非Py函數的定義,也就是不能完成非Py函數的閉包

? ? ? ?:Py函數的參數列表不能出現指針類型

? ? ? ? ?:其實整個項目里幾乎不怎么會出現Py函數,因為各個功能都是C函數實現的。可以說,在整個項目里,唯一的一個Py函數就是最后的主函數,以此匯總各個C類型C對象,來供Python調用。

????????(1)正確案例:

#cython: language_level=3
# -*- coding: UTF-8 -*-
# -*- file: test.pyx -*-#假設在test.pyx
from typing import Anycdef class MyClass(object):cdef bint myclasscdef bint say_hello() noexcept:print("Hello, Cython!", end = ' ')return 1def main(*args: tuple, **kwargs: dict) -> Any:cdef MyClass my = MyClass()my.myclass = say_hello()return my#經過編譯后:在test0.py
from test import *print(main().myclass) #最后輸出 Hello, Cython 1

?????????(2)錯誤實例:

#cython: language_level=3
# -*- coding: UTF-8 -*-
# -*- file: test.pyx -*-cdef object CFunction1() noexcept:  #正確!cdef void inter() noexcept:print("This is CFuntion1's inter")return intercdef object CFunction2() noexcept:  #正確!def void inter() -> None:print("This is CFuntion2's inter")return interdef PyFunction1() -> object:  #正確!def inter() -> None:print("This is PyFuntion1's inter")return interdef PyFunction2() -> object:  #錯誤!cdef void inter() noexcept:print("This is PyFuntion2's inter")return inter

三、cpdef定義關鍵字

?????????顧名思義,cpdef關鍵字定義的是一個CP函數/方法(CpFunction)既能被Cython調用又能被Python函數調用的函數。

? ? ? ? 雖然它叫CpFunction,其實它的規則就和CFunction類似

? ? ? ? 一般什么時候使用呢?就是一個函數,又需要在Python里使用,又需要在Cython里使用,那么它就可以派上用場了。。使用條件比較苛刻,也不利于性能

? ? ? ? 注意:

? ? ? ? ①:cpdef聲明的函數都是CpFunction。

? ? ? ? :將其修飾class則聲明成CFunction。

????????就現階段,我們僅僅需要知道如此就可以了,它用的不是很多。

四、DEF定義關鍵字:

? ? ? ? DEF關鍵字,一開始我遇到的時候是我在定義一個屬性叫DEF(防御力)的時候,結果說什么也不讓我命名,我一看好家伙都高亮了,結果發現還有這個關鍵字

? ? ? ? 其實,這就類似于C語言里的預處理(宏),就是#define預處理語句。

? ? ? ? 值得注意的是:

? ? ? ? :類似于C語言的#define語句,不需要寫類型,在編譯的時候會替換。

? ? ? ? :但也不如C語言的,因為僅僅只能定義基本的數據(str/ int/ float/ bytes)

? ? ? ? 當然還有其他的預處理指令比如IF/ ELSE,這些以后我會出專門的章節來講解的。

? ? ? ? 最后這些常量會被歸為Literal類型。?

五、編譯步驟

? ? ? ? ①:先編寫源文件.pyx: 創建Test.pyx

# cython language_level=3
# -*- coding: utf-8  -*-
# -*- file: Test.pyx -*-
# -*- CSDN: Daisy-Mo -*-
# -*- Git:  Rosysuki -*-cdef class Steps(object):cdef Steps say1(Steps self) noexcept:print("先編寫源文件")return selfcdef Steps say2(Steps self) noexcept:print("再編譯文件")return selfcdef Steps say3(Steps self) noexcept:print("最后調用擴展")return selfdef main(*args: tuple, **kwargs: dict) -> None:cdef Steps steps = Steps()(steps.say1().say2().say3())

? ? ? ? ②:再編寫setup.py文件:?

# -*- coding: utf-8  -*-
# -*- file: setup.py -*-from setuptools import setup
from Cython.Build import cythonizesetup(ext_modules = cythonize(["Test.pyx"])
)

? ? ? ? ③:然后編寫run.bat文件: 或者用cmd代替也可以

setup.py build_ext --inplace
PAUSE

? ?? ? ?點擊run.bat/在cmd里回車 之后運行,可得:? 就是那個.pyd文件

?????????

? ? ? ? ?④:檢測是否可用: 編寫main.py測試

from Test import mainmain()

? ? ? ? 結果是:?

?

-*- 休息線?-*-

我相信,通過我的這些總結和分享,大家能夠更加深入地了解Cython這個朋友,從而更有效地與它來一同優化自己的代碼。同時,我也期待能夠在這個過程中,與更多志同道合的朋友一起交流、學習和進步。

新春快樂🎇

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/65963.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/65963.shtml
英文地址,請注明出處:http://en.pswp.cn/web/65963.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Web開發(一)HTML5

Web開發&#xff08;一&#xff09;HTML5 寫在前面 參考黑馬程序員前端Web教程做的筆記&#xff0c;主要是想后面自己搭建網頁玩。 這部分是前端HTML5CSS3移動web視頻教程的HTML5部分。主要涉及到HTML的基礎語法。 HTML基礎 標簽定義 HTML定義 HTML(HyperText Markup Lan…

MATLAB學習筆記目錄

MATLAB學習筆記-生成純音并保存-CSDN博客 MATLAB學習筆記-各種格式之間的轉換 - 知乎 MATLAB學習筆記-胞組&#xff08;cell array&#xff09;轉換為矩陣&#xff0c;cell2mat_matlab如何把元胞數組改為矩陣-CSDN博客MATLAB學習筆記-判斷數組、結構體、數值、字符串是否相同…

Java-數據結構-棧與隊列(常考面試題與單調棧)

在上一篇的學習中&#xff0c;我們學習了棧和隊列的基本知識&#xff0c;以及它們對應都有哪些方法&#xff0c;在什么應用場景下如何使用&#xff0c;并且還對它們進行了模擬實現&#xff0c;而其實對于棧和隊列的相關知識還遠不止于此&#xff0c;而今天我們就對棧與隊列進行…

JSON.stringify(res,null,2)的含義

JSON.stringify(res, null, 2) 是 JavaScript 中將對象轉換為 JSON 字符串的方法&#xff0c;具體說明如下&#xff1a; 參數解釋 res&#xff1a;要轉換的對象。它可以是 JavaScript 中的任意類型&#xff0c;如對象、數組、字符串、數字等。例如&#xff0c;{name: "K…

Spring 項目 基于 Tomcat容器進行部署

文章目錄 一、前置知識二、本地Idea運行Spring項目1. 將寫好的 Spring 項目先打包成 war 包2. 查看項目工件&#xff08;Artifact&#xff09;是否存在3. 配置 Tomcat3.1 添加一個本地 Tomcat 容器3.2 將項目部署到 Tomcat 4. 運行項目 三、基于 Tomcat 部署及多實例部署1. Spr…

usbredir學習

文章目錄 背景典型場景編譯usbredirparserusbredirfilterusbredirparser/usbredirproto usbredirhostusbredirect/usbredirtestclient參考 背景 usbredir 是一種用于通過網絡轉發 USB 設備流量的網絡協議。它也是一個軟件包的名稱&#xff0c;該軟件包提供了一個解析庫、一個 …

ESXI 安裝教程(3) ---?vCenter Server 安裝

不涉及復雜的操作此項可不安裝 1.鏡像加載到虛擬光盤 對應的網盤文件 2.打開文件路徑 雙擊運行文件installer.exe 3.調整安裝語言 4.點擊安裝 5. 6. 證書,有效問題導致此提示,非專業網絡管理人員,不知道如何處理,此處點是即可 證書有效開始時間是安裝時間8小時 證書有效結束…

【初識掃盲】逆概率加權

我們正在處理一個存在缺失數據的回歸模型&#xff0c;并且希望采用一種非參數的逆概率加權方法來調整估計&#xff0c;以應對這種缺失數據的情況。 首先&#xff0c;我們需要明確問題的背景。我們有樣本 { ( Y i , X i , r i ) : i 1 , … , n } \left\{\left(Y_i, \boldsym…

極客說|Azure AI Agent Service 結合 AutoGen/Semantic Kernel 構建多智能體解決?案

作者&#xff1a;盧建暉 - 微軟高級云技術布道師 「極客說」 是一檔專注 AI 時代開發者分享的專欄&#xff0c;我們邀請來自微軟以及技術社區專家&#xff0c;帶來最前沿的技術干貨與實踐經驗。在這里&#xff0c;您將看到深度教程、最佳實踐和創新解決方案。關注「極客說」&am…

【集成學習】Boosting算法詳解

文章目錄 1. 集成學習概述2. Boosting算法詳解3. Gradient Boosting算法詳解3.1 基本思想3.2 公式推導 4. Python實現 1. 集成學習概述 集成學習&#xff08;Ensemble Learning&#xff09;是一種通過結合多個模型的預測結果來提高整體預測性能的技術。相比于單個模型&#xf…

小米vela系統(基于開源nuttx內核)——如何使用信號量進行PV操作

如何使用信號量進行PV操作 前言信號量1. 信號量簡介2. NuttX中信號量的創建與使用2.1 Nuttx信號量的初始化和銷毀2.2 信號量的等待和發布 3. 信號量的實際應用&#xff1a;下載任務示例3.1 實際代碼3.2 代碼說明3.3 執行說明 4. 信號量的優勢與應用場景5. 常見應用場景&#xf…

CMake學習筆記(2)

1. 嵌套的CMake 如果項目很大&#xff0c;或者項目中有很多的源碼目錄&#xff0c;在通過CMake管理項目的時候如果只使用一個CMakeLists.txt&#xff0c;那么這個文件相對會比較復雜&#xff0c;有一種化繁為簡的方式就是給每個源碼目錄都添加一個CMakeLists.txt文件&#xff…

旅游網站設計與實現

文末附有完整項目代碼 在當今數字化時代&#xff0c;旅游網站成為人們獲取旅游信息的重要途徑。本文將詳細介紹旅游網站的設計與實現&#xff0c;讓你輕松了解其中的技術奧秘&#xff01; 一、項目背景 隨著社會經濟的發展&#xff0c;人們對精神消費愈發重視&#xff0c;旅游…

【C++】size_t究竟是什么?全面解析與深入拓展

博客主頁&#xff1a; [小????????] 本文專欄: C 文章目錄 &#x1f4af;前言&#x1f4af;一、什么是size_t&#xff1f;為什么需要size_t&#xff1f; &#x1f4af;二、size_t的特性與用途1. size_t是無符號類型示例&#xff1a; 2. size_t的跨平臺適應性示例對…

【物流管理系統 - IDEAJavaSwingMySQL】基于Java實現的物流管理系統導入IDEA教程

有問題請留言或私信 步驟 下載項目源碼&#xff1a;項目源碼 解壓項目源碼到本地 打開IDEA 左上角&#xff1a;文件 → 新建 → 來自現有源代碼的項目 找到解壓在本地的項目源代碼文件&#xff0c;點擊確定&#xff0c;根據圖示步驟繼續導入項目 查看項目目錄&#xff…

ssh2-sftp-client和ssh2配合使用js腳本快速部署項目到服務器

有時候因為服務器不能實現github或者gitlab的自動部署服務&#xff0c;所以就需要使用腳本來實現自動部署&#xff0c;可以省時省力&#xff0c;一勞永逸。這里就使用ssh2-sftp-client和ssh2來實現&#xff0c;即便是需要sudo權限&#xff0c;也是可以的。 1.先將本地打包后的…

深度解析Linux中的調試器gdb/cgdb的使用

Linux下我們編譯好的代碼&#xff0c;無法直接調試 gcc/g默認的工作模式是realse模式 程序要調試的話&#xff0c;必須是debug模式&#xff0c;也就是說編譯的時候要加-g選項 gdb攜帶調試信息的exe 我們現在在文件夾里面創建一個文件lesson11 里面創建一個累加的代碼&…

【Maui】動態菜單實現(綁定數據視圖)

前言 .NET 多平臺應用 UI (.NET MAUI) 是一個跨平臺框架&#xff0c;用于使用 C# 和 XAML 創建本機移動和桌面應用。 使用 .NET MAUI&#xff0c;可從單個共享代碼庫開發可在 Android、iOS、macOS 和 Windows 上運行的應用。 .NET MAUI 是一款開放源代碼應用&#xff0c;是 X…

Bash語言的語法糖

Bash語言的語法糖 引言 在現代編程語言中&#xff0c;“語法糖”是一個非常常見的術語&#xff0c;它指的是那些使代碼更加易讀、易寫的語法特性。盡管這些特性并不改變語言的功能&#xff0c;但它們能顯著提升開發者的編程體驗。在眾多編程語言中&#xff0c;Bash&#xff0…

linux---Nginx詳細教程(包含安裝,網站部署)

Nginx是一個高性能的HTTP和反向代理服務器&#xff0c;也可以用作郵件代理服務器&#xff0c;其以占有內存少、并發能力強、穩定性高、豐富的功能集、低系統資源消耗而聞名。以下是對Nginx的詳細教程&#xff1a; 一、Nginx簡介 Nginx由俄羅斯人開發&#xff0c;第一個公開版…