Cython中def,cdef,cpdef的区别
这是我的第一篇翻译,希望大家多多给出意见和建议。
如有转载,请注明出处。
原文来自:https://stackoverflow.com/questions/28362009/definition-of-def-cdef-and-cpdef-in-cython
问题
我想知道在我声明一个函数时def
, cdef
, cpdef
的区别。
def
与其他两种的区别还算大致清晰。可是有时我见到声明时添加了返回值,有时见到的声明却没有添加返回值。
我还想知道在cython
中如何声明一个字符串变量,因为我不知道怎么搞,我就按照声明对象的方式做了。
回答0
def
用来在Python中声明一个函数。因为Cython是基于C runtime的,所以允许我们使用cpdef
。
cdef
在C语言层面声明了函数。正如我们所知道的在C语言中你必须为每一个函数定义返回值的类型。有事函数返回值为 void
,这就等于Python中的 return
。
Python是一个面向对象的语言。所以我们还可以在C++层面定义类方法,并在子类中重新。
举个栗子~
cdef class A:
cdef foo(self):
print "A"
cdef class B(A)
cdef foo(self, x=None)
print "B", x
cdef class C(B):
cpdef foo(self, x=True, int k=3)
print "C", x, k
总结一下,为什么我们要使用def
, cdef
, cpdef
呢?因为我们使用Cython,你的Python代码在编译之前,会被转换为C代码。鉴于此,我们可以控制会变成C代码的那些项目。
更多拓展的信息我还是建议你去看官方的文档。
http://docs.cython.org/src/reference/language_basics.html
回答1
最关键的不同在于 where the function can be called from,def
函数可以被Python和Cython调用,cdef
函数可以被Cython和C调用。
这两种类型的函数都是既可以被带类型的变量也可以被不带类型的变量被声明,并且都会被Cython编译为C。
# A Cython class for illustrative purposes
cdef class C:
pass
def f(int arg1, C arg2, arg3):
# takes an integer, a "C" and an untyped generic python object
pass
cdef g(int arg1, C arg2, arg3):
pass
上面的栗子中,f
对Python可见(一旦它被imported Cython module中。而 g
不可能被call from Python,它将被翻译成C signature:
PyObject* some_name(int, struct __pyx_obj_11name_of_module_C *, PyObject*)
其中的 struct __pyx_obj_11name_of_module_C *
是我们的 class C 翻译成的 C struct。这就允许我们把它传递给 C 函数,比如作为一个函数指针。
相对而言,f
就不能轻易的被C调用了。
cdef
函数的限制
cdef
函数不能在我们的函数内定义。这是因为没有方法可以存储获取变量在C函数指针,如下代码就是不允许的。
# WON'T WORK!
def g(a):
cdef (int b):
return a+b
cdef
函数不能处理 *args
*kwargs
类型的变量。这主要是因为它们不能轻易的翻译成 C signature。
cdef
函数的优势
cdef
函数可以接受任何类型的变量,包括哪些Python中没有的类型,比如指针。
def
函数总是返回一个Python对象,所以不能是一个具体返回值类型。
cdef int h(int* a):
# specify a return type and take a non-Python compatible argument
return a[0]
cdef
函数比 def
函数调用更快,因为它们会被翻译成一个更加简单的 C 函数调用。
cpdef
函数
cpdef
函数让Cython产生一个 cdef
函数(使得从Cython进行快速的函数调用)和一个 def
函数(使得我们可以从Pyhton调用)。就允许的变量类型而言,cpdef
函数具有 cdef
和 def
函数的限制。
什么时候使用 cdef
和 cpdef
函数?
一旦函数被调用,那么 cdef 和 def 函数内部代码的运行速度没有区别。
因此我们仅在以下条件下使用 cdef 函数:
- 需要传递非Python类型
- 需要传递它作为一个函数指针到C
- 需要经常调用(加速函数调用很重要)而且不需要从Python调用
使用 cpdef 函数的条件:
- 需要经常调用(所以使用加速函数调用很重要)而且需要从Python调用
Cython中def,cdef,cpdef的区别的更多相关文章
- 【转】python类中super()和__init__()的区别
[转]python类中super()和__init__()的区别 单继承时super()和__init__()实现的功能是类似的 class Base(object): def __init__(se ...
- Python中生成器和迭代器的区别(代码在Python3.5下测试):
https://blog.csdn.net/u014745194/article/details/70176117 Python中生成器和迭代器的区别(代码在Python3.5下测试):Num01–& ...
- 基于python中staticmethod和classmethod的区别(详解)
例子 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 class A(object): def foo(self,x): print "executing foo ...
- Python中send()和sendall()的区别
Python中send()和sendall()的区别 估计每个学习Python网络编程的人,都会遇到过这样的问题: send()和sendall()到底有什么区别? send()和sendall()原 ...
- python中_new_()与_init_()的区别
__new__方法的使用 只有继承于object的新式类才能有__new__方法,__new__方法在创建类实例对象时由Python解释器自动调用,一般不用自己定义,Python默认调用该类的直接父类 ...
- 【转】为什么我们都理解错了HTTP中GET与POST的区别
GET和POST是HTTP请求的两种基本方法,要说它们的区别,接触过WEB开发的人都能说出一二. 最直观的区别就是GET把参数包含在URL中,POST通过request body传递参数. 你可能自己 ...
- Visual Studio 中 Build 和 Rebuild 的区别
因为之前写的程序比较小,编译起来比较快,所以一直都没有太在意 Build 和 Rebuild 之间的区别,后来发现两个还是有很大不同. Build 只针对在上次编译之后更改过的文件进行编译,在项目比较 ...
- SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别
SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别 MSSQL为我们提供了两种动态执行SQL语句的命令,分别是 EXEC 和 SP_EXECUTESQL ,我们先来看一下两种方 ...
- java集合中List与set的区别
java集合中List与set的区别. List可以存储元素为有序性并且元素可以相同. set存储元素为无序性并且元素不可以相同. 下面贴几段代码感受一下: ArrayL ...
随机推荐
- JS高级程序设计第三版——在HTML中使用JavaScript
使用<script>元素的方式 外部引用式.行内式.嵌入式. JavaScript引用放在<body>后面的原因 假如在文档的<head>元素中包含所有JavaSc ...
- [图]Windows 10 Build 16273版本更新发布:新增可变式字体Bahnschrift
在经历了长达三周的等待之后,微软于今天终于面向Windows Insider项目的Fast通道用户发布了Windows 10 Build 16273版本更新.事实上,微软应该会在两周前就应该发布新版本 ...
- ZT 父子进程共享文件描述符
转贴自倒霉熊的博客 [linux学习笔记-2]父子进程共享文件描述符 (2009-03-02 23:03:17) 转载▼ 标签: 学习 linux 子进程 文件描述符 杂谈 分类: 学习 #inclu ...
- lua 语句学习
就如同C里的if else,while,do,repeat.就看lua里怎么用: 1.首先看if else t = {1,2,3} local i = 1 if t[i] and t[i] % 2 = ...
- Velocity 模板
Velocity 模板引擎介绍 引:https://www.ibm.com/developerworks/cn/java/j-lo-velocity1/ 在 现今的软件开发过程中,软件开发人员将更多的 ...
- 数字游戏II
题面好难找:嘟嘟嘟 贪心 + dp. 首先要按bi的降序排序,让每一次减少大的数尽量靠前.为啥咧?于是我们就需要证明:令sum = a1 - (1 - 1) * b1 + a2 - (2 - 1) * ...
- 【转】Js中Prototype、__proto__、Constructor、Object、Function关系介绍
一 Prototype.__proto__与Object.Function关系介绍 Function.Object:Js自带的函数对象. prototype,每一个 ...
- HashMap中的equals和hashCode
HashMap的存储方式 HashMap的实现方式是数组链,不同的对象根据其哈希码(hashCode方法的返回值)找到对应的数组下标,然后存入数组.不同的对象有相同的哈希码时怎么办?这就由数组链中的链 ...
- JavaScript常用方法
判断运行客户端 function isPhone() { var flag = false; var userAgentInfo = navigator.userAgent; var Agents = ...
- 【洛谷P1983】车站分级
车站分级 题目链接 首先,可以发现火车停靠站点的大小是没有什么规律的, 火车可以停靠在级别<=当前级别的站点,必须停靠在级别>=当前最高级别的站点 但是所有没有被停靠的站点级别一定比所有被 ...