Cython 的宏定义

简介: Cython 的宏定义

我们知道在 C 里面可以使用 #define 定义一个宏,这在 Cython 里面也是可以的,不过使用的是 DEF 关键字。

DEF NUMBER = 123
DEF NAME = "古明地觉"
print(NUMBER)
print(NAME)
"""
123
古明地觉
"""

DEF 定义的宏在编译的时候会被替换成我们指定的值,但是需要注意:宏对应的值必须在编译的时候就能确定,我们不能给宏赋一个运行时才能构建的值。举个例子:

DEF ARRAY = [1, 2, 3, 4]
print(ARRAY)

这行代码编译时会报错,因为列表需要运行时动态构建.


但元组是可以的,因为元组在编译的时候就会作为一个常量加载进来。

DEF ARRAY = (1, 2, 3, 4)
print(ARRAY)  # (1, 2, 3, 4)

另外我们知道 C 里面的宏是可以带参数的,但在 Cython 里面不支持。所以在 Cython 里面使用宏的话,替换的一般都是数值、字符串之类的

在 C 里面还可以使用 IF ELIF ELSE 进行条件编译,Cython 也是支持的。

DEF SYSNAME = "Windows"
IF SYSNAME == "Windows":
    print("这是 Windows")
ELIF SYSNAME == "Darwin":
    print("这是 Mac OS")
ELIF SYSNAME == "Linux":
    print("这是 Liunx")
ELSE:
    print("其它类型的系统")

该文件在编译之后实际上只有两行:

DEF SYSNAME = "Windows"
print("这是 Windows")

当不同的系统,需要执行不同的逻辑时,IF ELIF ELSE 就很有用。为此,Cython 提供了几个预定义的宏,专门用于判断操作系统类型。

  • UNAME_SYSNAME:操作系统的名称;
  • UNAME_RELEASE:操作系统的发行版;
  • UNAME_VERSION:操作系统的版本;
  • UNAME_MACHINE:操作系统的机型、或者硬件名称;
  • UNAME_NODENAME:网络名称;


IF UNAME_SYSNAME == "Windows":
    print("这是 Windows")
ELIF UNAME_SYSNAME == "Darwin":
    print("这是 Mac OS")
ELIF UNAME_SYSNAME == "Linux":
    print("这是 Liunx")
ELSE:
    print("其它类型的系统")
"""
这是 Windows
"""

这些宏都是预定义好的,但必须搭配 IF ELIF ELSE 使用,否则报错。


阶段性小结




到目前为止,我们深入介绍了 Cython 的语言特性,并且为了更好地理解,我们使用了很多 CPython 解释器里面才出现的术语,比如:PyObject、PyFunctionObject 等等。在学习 Cython 的某些知识时相当于站在了解释器的角度上,当然也介绍了 CPython 解释器的一些知识。

我们后续将会以这些特性为基础,进行深入地使用。

Cython是一个辅助语言,它是建立在 Python 之上的,为 Python 提供扩展模块。但程序的性能瓶颈,一般是由百分之二十的代码决定的,所以很少有项目会完全使用 Cython 编写(uvloop 例外),但它确实是一个成熟的语言,有自己的语法(个人非常喜欢,觉得设计的真酷)。在 GitHub 上搜索,会发现大量的 Cython 源文件分布在众多的存储库中。

考虑到 numpy, pandas, scipy, sklearn 等知名模块内部都在使用,所以 Cython 也算是被数百万的开发人员、分析师、工程师和科学家直接或者间接使用。

如果 Pareto 原理是可信的,程序中百分之 80 的运行时开销是由百分之 20 的代码引起的,那么对于一个 Python 项目来说,只需要将少部分 Python 代码转换成 Cython 代码即可。

另外我们发现,用到 Cython 的顶尖项目都与数据分析和科学计算有关,这并非偶然。Cython 之所以会在这些领域大放异彩,有以下几个原因:

1)Cython 可以高效且简便地封装现有的 C, C++, FORTRAN 库,从而对那些已经优化并调试过的功能进行访问。这里多提一句,FORTRAN算是一个上古的语言了,它的历史比 C 还要早,不过别看它出现的早、但速度是真的快,尤其是在数值计算方面甚至比 C 还要快。

包括 numpy 使用的 blas 内部也用到了 FORTRAN,虽然 FORTRAN 编写代码异常的痛苦,但是它在一些学术界和工业界还是具有一席之地的。原因就是它内部的一些算法,都是经过大量的优化、并且久经考验的,直接拿来用就可以。而 Cython 也提供了相应的姿势来调用 FORTRAN 已经编写好的功能。

2)当转化为静态类型时,内存和 CPU 密集的 Python 计算会有更好的执行性能。

3)在处理大型的数据集时,与 Python 内置的数据结构相比,在低级别控制精确的数据类型和数据结构可以让存储更高效、执行性能更优秀。

4)Cython 可以和 C, C++, FORTRAN 库共享同类型的连续数组,并通过 numpy 的数组直接暴露给 Python。

虽说用到 Cython 的一些顶尖项目都是和数据科学相关的,但即便不是在数据分析和科学计算领域,Cython 也可以大放异彩,因为它还能加速一般的 Python 代码,包括数据结构密集型算法。例如:lxml 这个高性能的 xml 解析器内部就大量使用了 Cython。因此即使它不在科学计算和数据分析的保护伞下,也依旧有很大的用途。

相关文章
|
存储 前端开发 算法
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析(一)
C++线程 并发编程:std::thread、std::sync与std::packaged_task深度解析
1072 0
|
8月前
|
传感器 网络协议 算法
《多账号同源识别核心技术拆解:从行为指纹到身份锚定的实操逻辑》
本文聚焦同一用户多账号同源识别的核心技术路径,跳出传统单一标识校验思维,深度拆解行为、设备、网络、数据等多维度识别手段的实操逻辑。从行为基因图谱构建、硬件隐性特征聚合,到网络轨迹指纹链打造、交互惯性图谱搭建,再到跨账号数据锚点联动,系统梳理各层级核心技术的落地思路,重点提炼隐性特征萃取、多维度协同校准等关键方法,规避标识篡改、IP切换、行为伪装等识别痛点。通过构建多维度特征融合校准体系,平衡识别精度与隐私合规,形成“全链路特征协同-置信度分级决策-误判动态修正”的闭环逻辑,为复杂场景下多账号精准识别提供兼具深度与实操性的技术参考,助力搭建抗干扰、高精准的同源账号识别体系。
683 11
|
11月前
|
前端开发 JavaScript CDN
除了Promise.all,还有哪些方法可以处理多个异步操作?
除了Promise.all,还有哪些方法可以处理多个异步操作?
499 128
|
Go C语言 Python
使用 Cython 包装外部的 C 代码
使用 Cython 包装外部的 C 代码
417 0
|
弹性计算 Prometheus 运维
一文详解阿里云可观测体系下标签最佳实践
在当今数字化转型加速的时代,企业 IT 系统的复杂度与日俱增,如何高效地管理和监控这些系统成为了一项挑战。阿里云作为全球领先的云计算服务商,提供了一整套全面的可观测性解决方案,覆盖从业务、端侧(小程序、APP、H5 等)、应用、中间件、容器/ECS 等全栈的监控体系,旨在帮助企业构建强大而灵活的可观测性体系。其中,标签(Tag)作为一种核心组织和管理手段,在阿里云可观测体系中扮演着至关重要的角色。本文将深入探讨阿里云可观测系列产品中标签的应用,以及如何运用标签在阿里云可观测产品体系下进行体系化建设并给出相关最佳实践。
1405 219
|
机器学习/深度学习 人工智能 自然语言处理
音频基座大模型FunAudioLLM评测
通义语音团队最新开源了音频基座大模型FunAudioLLM,包含两大模型SenseVoice和CosyVoice。本文对这两种大模型进行整体的评测。
909 1
音频基座大模型FunAudioLLM评测
|
Rust 编译器 C++
使用 def、cdef、cpdef 创建函数
使用 def、cdef、cpdef 创建函数
510 0
|
Linux Shell 开发者
关于Linux上的$ORIGIN解说
适当应用 `$ORIGIN`,你的应用程序将更加灵活,更易于分发和部署。
859 5
|
Web App开发
JavaWeb - HTTP 请求中 Post 和 Put 区别
JavaWeb - HTTP 请求中 Post 和 Put 区别
527 0