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.rhkb.cn/news/1356.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WINFORM - DevExpress -> DevExpress总结[安装、案例]

安装devexpress软件 路径尽量不换&#xff0c;后面破解不容易出问题 vs工具箱添加控件例如: ①使用控制台进入DevExpress安装目录: cd C:\Program Files (x86)\DevExpress 20.1\Components\Tools ②添加DevExpress控件&#xff1a; ToolboxCreator.exe/ini:toolboxcreator…

primitive 的 Appearance编写着色器材质

import { nextTick, onMounted, ref } from vue import * as Cesium from cesium import gsap from gsaponMounted(() > { ... })// 1、创建矩形几何体&#xff0c;Cesium.RectangleGeometry&#xff1a;几何体&#xff0c;Rectangle&#xff1a;矩形 let rectGeometry new…

《JavaWeb开发-javascript基础》

文章目录 《JavaWeb开发-javascript基础》1.javascript 引入方式2.JS-基础语法-书写语法2.1 书写语法2.2 输出语句 3.JS-基础语法-变量4.JS-基础语法-数据类型&运算符4.1 数据类型4.2 运算符4.3 数据类型转换 5. JS-函数6. JS-对象-Array数组7. JS-对象-String字符串8. JS-…

从CentOS到龙蜥:企业级Linux迁移实践记录(龙蜥开局)

引言&#xff1a; 在我们之前的文章中&#xff0c;我们详细探讨了从CentOS迁移到龙蜥操作系统的基本过程和考虑因素。今天&#xff0c;我们将继续这个系列&#xff0c;重点关注龙蜥系统的实际应用——特别是常用软件的安装和配置。 龙蜥操作系统&#xff08;OpenAnolis&#…

【python基础——异常BUG】

什么是异常(BUG) 检测到错误,py编译器无法继续执行,反而出现错误提示 如果遇到错误能继续执行,那么就捕获(try) 1.得到异常:try的执行,try内只可以捕获一个异常 2.预案执行:except后面的语句 3.传入异常:except … as uestcprint(uestc) 4.没有异常:else… 5.鉴定完毕,收尾的语…

MySQL的安装

MySQL典型的关系型数据库&#xff08;RDBMS&#xff09;&#xff1a;oracle、MySQL、SqlServer MySQL的版本 5.5~5.7、8.0 MySQL的安装和配置 下载地址&#xff1a; https://downloads.mysql.com/archives/community/ 安装包 (x86, 64-bit), MSI Installer 执行下一步即…

跨境电商领域云手机之选:亚矩阵云手机的卓越优势

在跨境电商蓬勃发展的当下&#xff0c;云手机已成为众多企业拓展海外市场的得力助手。亚矩阵云手机凭借其独特优势&#xff0c;在竞争激烈的云手机市场中崭露头角。不过&#xff0c;鉴于市场上云手机服务供应商繁多&#xff0c;企业在抉择时需对诸多要素予以审慎考量。 跨境电商…

【论文阅读】MAMBA系列学习

Mamba code&#xff1a;state-spaces/mamba: Mamba SSM architecture paper&#xff1a;https://arxiv.org/abs/2312.00752 背景 研究问题&#xff1a;如何在保持线性时间复杂度的同时&#xff0c;提升序列建模的性能&#xff0c;特别是在处理长序列和密集数据&#xff08;如…

Java100道面试题

1.JVM内存结构 1. 方法区&#xff08;Method Area&#xff09; 方法区是JVM内存结构的一部分&#xff0c;用于存放类的相关信息&#xff0c;包括&#xff1a; 类的结构&#xff08;字段、方法、常量池等&#xff09;。字段和方法的描述&#xff0c;如名称、类型、访问修饰符…

【华为云开发者学堂】基于华为云 CodeArts CCE 开发微服务电商平台

实验目的 通过完成本实验&#xff0c;在 CodeArts 平台完成基于微服务的应用开发&#xff0c;构建和部署。 ● 理解微服务应用架构和微服务模块组件 ● 掌握 CCE 平台创建基于公共镜像的应用的操作 ● 掌握 CodeArts 平台编译构建微服务应用的操作 ● 掌握 CodeArts 平台部署微…

C#学习笔记 --- 简单应用

1.operator 运算符重载&#xff1a;使自定义类可以当做操作数一样进行使用。规则自己定。 2.partial 分部类&#xff1a; 同名方法写在不同位置&#xff0c;可以当成一个类使用。 3.索引器&#xff1a;使自定义类可以像数组一样通过索引值 访问到对应的数据。 4.params 数…

用python编写一个放烟花的小程序

import pygame import random # 代码解释及使用说明&#xff1a; # 首先&#xff0c;导入 pygame 和 random 库。pygame 用于创建游戏窗口和图形绘制&#xff0c;random 用于生成随机数。 # 初始化 pygame&#xff0c;并设置屏幕尺寸为 800x600 像素&#xff0c;设置窗口标题为…

栈 (算法十二)

1.删除字符串中的所有相邻项 link:1047. 删除字符串中的所有相邻重复项 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 栈&#xff0b;模拟 code class Solution { public:string removeDuplicates(string s) {// 栈来模拟即可// string代替栈string ans;for(…

特制一个自己的UI库,只用CSS、图标、emoji图 第二版

图&#xff1a; 代码&#xff1a; index.html <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>M…

Linux第二课:LinuxC高级 学习记录day01

0、大纲 0.1、Linux 软件安装&#xff0c;用户管理&#xff0c;进程管理&#xff0c;shell 命令&#xff0c;硬链接和软连接&#xff0c;解压和压缩&#xff0c;功能性语句&#xff0c;结构性语句&#xff0c;分文件&#xff0c;make工具&#xff0c;shell脚本 0.2、C高级 …

数据结构(Java版)第八期:LinkedList与链表(三)

专栏&#xff1a;数据结构(Java版) 个人主页&#xff1a;手握风云 目录 一、链表中的经典面试题 1.1. 链表分割 1.2. 链表的回文结构 1.3. 相交链表 1.4. 环形链表 一、链表中的经典面试题 1.1. 链表分割 题目中要求不能改变原来的数据顺序&#xff0c;也就是如上图所示。…

自动连接校园网wifi脚本实践(自动网页认证)

目录 起因执行步骤分析校园网登录逻辑如何判断当前是否处于未登录状态&#xff1f; 书写代码打包设置开机自动启动 起因 我们一般通过远程控制的方式访问实验室电脑&#xff0c;但是最近实验室老是断电&#xff0c;但重启后也不会自动连接校园网账户认证&#xff0c;远程工具&…

【TI毫米波雷达】DCA1000不使用mmWave Studio的数据采集方法,以及自动化实时数据采集

【TI毫米波雷达】DCA1000不使用mmWave Studio的数据采集方法&#xff0c;以及自动化实时数据采集 mmWave Studio提供的功能完全够用了 不用去纠结用DCA1000低延迟、无GUI传数据 速度最快又保证算力无非就是就是Linux板自己写驱动做串口和UDP 做雷达产品应用也不会采用DCA1000的…

目标检测中的Bounding Box(边界框)介绍:定义以及不同表示方式

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

【C语言】获取文件属性

目录 1. stat函数 2. 获取文件属性 3. 获取文件权限 1. stat函数 int stat(const char *path, struct stat *buf); 功能&#xff1a;获取文件属性 参数&#xff1a; path&#xff1a;文件路径名buf&#xff1a;保存文件属性信息的结构体 返回值&#xff1a;成功&#xff1…