py3里如何让一个函数只调用.py另一个函数的返回值

Python 3 教程
Python3 函数
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。
定义一个函数
你可以定义一个由自己想要功能的函数,以下是简单的规则:
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
函数内容以冒号起始,并且缩进。
return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
Python 定义函数使用 def 关键字,一般格式如下:
def 函数名(参数列表):
默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配起来的。
让我们使用函数来输出"Hello World!":
&&&def hello() :
print(&Hello World!&)
&&& hello()
Hello World!
更复杂点的应用,函数中带上参数变量:
实例(Python 3.0+)
def area(width, height):
return width * height
def print_welcome(name):
print(&Welcome&, name)
print_welcome(&Runoob&)
print(&width =&, w, & height =&, h, & area =&, area(w, h))
以上实例输出结果:
Welcome Runoob
height = 5
定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。
如下实例调用了 printme() 函数:
实例(Python 3.0+)
def printme( str ):
&打印任何传入的字符串&
print (str)
printme(&我要调用用户自定义函数!&)
printme(&再次调用同一函数&)
以上实例输出结果:
我要调用用户自定义函数!
再次调用同一函数
在 python 中,类型属于对象,变量是没有类型的:
a="Runoob"
以上代码中,[1,2,3] 是 List 类型,"Runoob" 是 String 类型,而变量 a 是没有类型,她仅仅是一个对象的引用(一个指针),可以是指向 List 类型对象,也可以是指向 String 类型对象。
可更改(mutable)与不可更改(immutable)对象
在 python 中,strings, tuples, 和 numbers 是不可更改的对象,而 list,dict 等则是可以修改的对象。
不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。
可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。
python 函数的参数传递:
不可变类型:类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
可变类型:类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响
python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
python 传不可变对象实例
实例(Python 3.0+)
def ChangeInt( a ):
ChangeInt(b)
print( b )
实例中有 int 对象 2,指向它的变量是 b,在传递给 ChangeInt 函数时,按传值的方式复制了变量 b,a 和 b 都指向了同一个 Int 对象,在 a=10 时,则新生成一个 int 值对象 10,并让 a 指向它。
传可变对象实例
可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。例如:
实例(Python 3.0+)
def changeme( mylist ):
&修改传入的列表&
mylist.append([1,2,3,4])
print (&函数内取值: &, mylist)
mylist = [10,20,30]
changeme( mylist )
print (&函数外取值: &, mylist)
传入函数的和在末尾添加新内容的对象用的是同一个引用。故输出结果如下:
函数内取值:
[10, 20, 30, [1, 2, 3, 4]]
函数外取值:
[10, 20, 30, [1, 2, 3, 4]]
以下是调用函数时可使用的正式参数类型:
关键字参数
不定长参数
必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
调用printme()函数,你必须传入一个参数,不然会出现语法错误:
实例(Python 3.0+)
def printme( str ):
&打印任何传入的字符串&
print (str)
以上实例输出结果:
Traceback (most recent call last):
File "test.py", line 10, in &module&
TypeError: printme() missing 1 required positional argument: 'str'
关键字参数
关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。
使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。
以下实例在函数 printme() 调用时使用参数名:
实例(Python 3.0+)
def printme( str ):
&打印任何传入的字符串&
print (str)
printme( str = &菜鸟教程&)
以上实例输出结果:
以下实例中演示了函数参数的使用不需要使用指定顺序:
实例(Python 3.0+)
def printinfo( name, age ):
&打印任何传入的字符串&
print (&名字: &, name)
print (&年龄: &, age)
printinfo( age=50, name=&runoob& )
以上实例输出结果:
调用函数时,如果没有传递参数,则会使用默认参数。以下实例中如果没有传入 age 参数,则使用默认值:
实例(Python 3.0+)
def printinfo( name, age = 35 ):
&打印任何传入的字符串&
print (&名字: &, name)
print (&年龄: &, age)
printinfo( age=50, name=&runoob& )
print (&------------------------&)
printinfo( name=&runoob& )
以上实例输出结果:
------------------------
不定长参数
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述 2 种参数不同,声明时不会命名。基本语法如下:
def functionname([formal_args,] *var_args_tuple ):
"函数_文档字符串"
function_suite
return [expression]
加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。
实例(Python 3.0+)
def printinfo( arg1, *vartuple ):
&打印任何传入的参数&
print (&输出: &)
print (arg1)
print (vartuple)
printinfo( 70, 60, 50 )
以上实例输出结果:
如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。如下实例:
实例(Python 3.0+)
def printinfo( arg1, *vartuple ):
&打印任何传入的参数&
print (&输出: &)
print (arg1)
for var in vartuple:
print (var)
printinfo( 10 )
printinfo( 70, 60, 50 )
以上实例输出结果:
还有一种就是参数带两个星号 **基本语法如下:
def functionname([formal_args,] **var_args_dict ):
"函数_文档字符串"
function_suite
return [expression]
加了两个星号 ** 的参数会以字典的形式导入。
实例(Python 3.0+)
def printinfo( arg1, **vardict ):
&打印任何传入的参数&
print (&输出: &)
print (arg1)
print (vardict)
printinfo(1, a=2,b=3)
以上实例输出结果:
{'a': 2, 'b': 3}
声明函数时,参数中星号 * 可以单独出现,例如:
def f(a,b,*,c):
return a+b+c
如果单独出现星号 * 后的参数必须用关键字传入。
&&& def f(a,b,*,c):
return a+b+c
&&& f(1,2,3)
Traceback (most recent call last):
File "&stdin&", line 1, in &module&
TypeError: f() takes 2 positional arguments but 3 were given
&&& f(1,2,c=3) # 正常
python 使用 lambda 来创建匿名函数。
所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
lambda 只是一个表达式,函数体比 def 简单很多。
lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
lambda 函数的语法只包含一个语句,如下:
lambda [arg1 [,arg2,.....argn]]:expression
如下实例:
实例(Python 3.0+)
sum = lambda arg1, arg2: arg1 + arg2
print (&相加后的值为 : &, sum( 10, 20 ))
print (&相加后的值为 : &, sum( 20, 20 ))
以上实例输出结果:
相加后的值为 :
相加后的值为 :
return语句
return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的return语句返回None。之前的例子都没有示范如何返回数值,以下实例演示了 return 语句的用法:
实例(Python 3.0+)
def sum( arg1, arg2 ):
total = arg1 + arg2
print (&函数内 : &, total)
return total
total = sum( 10, 20 )
print (&函数外 : &, total)
以上实例输出结果:
变量作用域
Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有4种,分别是:
L (Local) 局部作用域
E (Enclosing) 闭包函数外的函数中
G (Global) 全局作用域
B (Built-in) 内建作用域
以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。
x = int(2.9)
# 内建作用域
g_count = 0
# 全局作用域
def outer():
o_count = 1
# 闭包函数外的函数中
def inner():
i_count = 2
# 局部作用域
Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问,如下代码:
&&& if True:
msg = 'I am from Runoob'
'I am from Runoob'
实例中 msg 变量定义在 if 语句块中,但外部还是可以访问的。
如果将 msg 定义在函数中,则它就是局部变量,外部不能访问:
&&& def test():
msg_inner = 'I am from Runoob'
&&& msg_inner
Traceback (most recent call last):
File "&stdin&", line 1, in &module&
NameError: name 'msg_inner' is not defined
从报错的信息上看,说明了 msg_inner 未定义,无法使用,因为它是局部变量,只有在函数内可以使用。
全局变量和局部变量
定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下实例:
实例(Python 3.0+)
def sum( arg1, arg2 ):
total = arg1 + arg2
print (&函数内是局部变量 : &, total)
return total
sum( 10, 20 )
print (&函数外是全局变量 : &, total)
以上实例输出结果:
函数内是局部变量 :
函数外是全局变量 :
global 和 nonlocal关键字
当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字了。
以下实例修改全局变量 num:
实例(Python 3.0+)
def fun1():
global num
print(num)
print(num)
print(num)
以上实例输出结果:
如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了,如下实例:
实例(Python 3.0+)
def outer():
def inner():
nonlocal num
print(num)
print(num)
以上实例输出结果:
另外有一种特殊情况,假设下面这段代码被运行:
实例(Python 3.0+)
def test():
以上程序执行,报错信息如下:
Traceback (most recent call last):
File "test.py", line 7, in &module&
File "test.py", line 5, in test
UnboundLocalError: local variable 'a' referenced before assignment
错误信息为局部作用域引用错误,因为 test 函数中的 a 使用的是局部,未定义,无法修改。
修改 a 为全局变量,通过函数参数传递,可以正常执行输出结果为:
实例(Python 3.0+)
def test(a):
执行输出结果为:
感谢您的支持,我会继续努力的!
扫码打赏,你说多少就多少
记住登录状态
重复输入密码C++使用Py*调用Python3模块中类成员函数及数组参数传递 - 简书
C++使用Py*调用Python3模块中类成员函数及数组参数传递
1.首先来看Python模块的部分结构和代码。ssd_network_classify.py文件中有SSD_Network_Classify类及其识别的成员函数detect_image(),返回值是一个1维的不定长double型数组。
class SSD_Network_Classify:
#其他函数实现省略。。。
def detect_image(self, img_raw=None):
获取图片数据进行检测。
:param img_raw: 从c++传来的一维480*640*3大小的int型图片数据(包含负值)
:return: 返回的是一维数组
#将原始图片数据shape成480*640*3的uint8类型数据。
img_data = np.reshape(img_raw, (480, 640, 3)).astype(np.uint8)
#以下两行输出用于显示传参的值帮助理解。
print(img_data.shape)
print(img_data)
#进行目标检测并返回检测结果。
rclasses, rscores, rbboxes = self.detect(img_data)
#显示检测结果
cv2.imshow('DetectImage', img_data)
cv2.waitKey(1)
#以下将返回的结果拼接成一维的数组返回给调用该函数的c程序中。
rclasses = np.reshape(rclasses, (-1, 1))
rscores = np.reshape(rscores, (-1, 1))
result = np.concatenate([rclasses, rscores, rbboxes], axis=1)
result = np.squeeze(np.reshape(result, (1, -1)))
#print(result)
return result
在Python中输出传入的参数(从c++传送过来)示例如下:
2. C++端获取摄像头数据的类CameraBase:
//以下是.h文件中的成员变量
//cv::VideoCapture *
//cv::Mat bgr_
//int device_
//以下是.cpp中主要成员函数的实现
"构造函数,打开摄像头"
CameraBase::CameraBase(int dev_num) {
this-&device_num = dev_
this-&capture = new cv::VideoCapture(this-&device_num);
if (!capture-&isOpened()) {
std::cout && "camera open failed\n";
"读取网络摄像头的图片数据"
void CameraBase::grabImages() {
this-&capture-&read(this-&bgr_image);
"图片的Mat数据转换成char类型的数组数据"
char *CameraBase::bgrImageMatToArray( char *img_arr) {
size_t img_size = this-&bgr_image.total() * this-&bgr_image.elemSize() ;
std::memcpy(img_arr, this-&bgr_image.data, img_size * sizeof(char));
return img_
3.核心部分。main.cpp中c++调用Python的函数callPythonForDetect。这块代码是c++调用Python的核心代码,具体代码解释已经在代码注释中写得很清楚了。
int callPythonForDetect() {
//调用web摄像头进行处理
CameraBase *camera = new CameraBase();
//------------------以下是调用Python模块的代码------------------//
//python环境初始化
Py_Initialize();
if (!Py_IsInitialized())
return -1;
//导入系统包用于扩展需要加载的Python模块的路径,否则即使Python模块在当前目录也无法加载
PyRun_SimpleString("import sys \nsys.argv = ['']");
//加载Python模块的路径
PyRun_SimpleString("sys.path.append('/absolute/path/to/python/module')");
//导入需要调用的模块
PyObject *pyModule = PyImport_ImportModule("ssd_network_classify");
if (!pyModule) {
printf("Can not open python module\n");
return -1;
//获取python模块中的类名并创建对象实例
PyObject *pyClass = PyObject_GetAttrString(pyModule, "SSD_Network_Classify");
PyObject *pyClassInstance = PyObject_CallObject(pyClass, NULL);
//获取Python模块中相应的函数名
PyObject *pyFunc = PyObject_GetAttrString(pyClass, "detect_image");
//声明或定义变量
npy_intp IMGSHAPE[1] = {480 * 640 * 3};//图片数据的shape参数值
char *img_data = new char[IMGSHAPE[0]];//从摄像头中获取的图片数据保存的变量
PyByteArrayObject *pyIMgA//image数组的Python对象
//设置发送给Python函数的参数对象
PyObject *pyArgs = PyTuple_New(2);
while (true) {
camera-&grabImages();//获取摄像头数据
//获取image数据并保存至img_data数组中
camera-&bgrImageMatToArray(img_data);
//必须添加如下函数,否则无法执行PyArray_SimpleNewFromData
import_array ();
//将c的img数组数据转换成pyobject类型的数组数据
pyIMgArr = reinterpret_cast&PyByteArrayObject *&
(PyArray_SimpleNewFromData(1, IMGSHAPE, NPY_BYTE, reinterpret_cast&void *&(img_data)));
//设置调用函数的self值为前面该类创建的实例,否则无法使用self变量进行调用而出错
PyTuple_SetItem(pyArgs, 0, Py_BuildValue("O", pyClassInstance));
//设置变量的第二个参数值为byte类型的数组作为图片数据
PyTuple_SetItem(pyArgs, 1, reinterpret_cast&PyObject *&(pyIMgArr));
//调用python函数进行识别任务并返回相应的结果
PyObject *pyResult = PyObject_CallObject(pyFunc, pyArgs);
//以下是对返回的一维数组结果进行处理
if (pyResult) {
//将结果类型转换成数组对象类型
PyArrayObject *pyResultArr = (PyArrayObject *) pyR
//也可以使用以下两行代码来代替上面的类型转换。
//PyArray_Descr *descr = PyArray_DescrFromType(NPY_DOUBLE);
//PyArrayObject *pyResultArr = (PyArrayObject*)PyArray_FromAny(pyResult, descr,1,1,NPY_ARRAY_C_CONTIGUOUS,NULL);
//从Python中的PyArrayObject解析出数组数据为c的double类型。
double *resDataArr = (double *) PyArray_DATA(pyResultArr);
int dimNum = PyArray_NDIM(pyResultArr);//返回数组的维度数,此处恒为1
npy_intp *pdim = PyArray_DIMS(pyResultArr);//返回数组各维度上的元素个数值
//以下是对返回结果的输出显示
for (int i = 0; i & dimN ++i) {
for (int j = 0; j & pdim[0]; ++j)
cout && resDataArr[i * pdim[0] + j] && ",";
//释放Python环境
Py_Finalize();
从调用的Python函数中返回的数组结果示例如下:
dataout.png
以下是最终C++通过调用Python版本实现的目标识别网络展示的结果:
result.png
*** 使用C++调用python3模块接口的示例基本没有,有的大部分都是python2版本的示例,而新版本的很多函数名称和用法改变都很大,导致我在写这块代码的时候碰到很多问题,就这个简单需求花了我整整3天的时间,期间有考虑使用第三方框架进行解决,但是发现也很麻烦。其中需要注意的是,因为Python的类函数的第一个参数是self,并且是传入对象本身,因此在c中调用的时候也要考虑为其赋值(PyTuple_SetItem(pyArgs, 0, Py_BuildValue("O", pyClassInstance)); 这行代码很重要),否则会出错。很多例子都考虑的是调用非类成员函数,因此不需要考虑self变量而比较容易。我是自己尝试很久并经过调试才知道该怎么给self赋值的,这也是我写这篇文章的原因所在,希望给其他需要的人一些参考,少走弯路。***
魔法方法的详解: http://pyzh.readthedocs.io/en/latest/python-magic-methods-guide.html#id5 本指南归纳于我的几个月的博客,主题是魔法方法。 什么是魔法方法呢?它们在面向对象的Python的处处皆是。它们...
因为,全文比较长,没有经过完整的校对,纰漏难免。 当前最新版本的 pdf 在此 -& 简明python指南(.9.7.pdf 以下内容是为了方便搜索引擎索引特别加上的,不是给人看的。因此不进行频繁修补,只做积累更新(最后更新于日)。...
苹果官方文档翻译 《Objective-C语言编程》(Programming with Objective-C) https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Programmi...
原文地址:C语言函数调用栈(一)C语言函数调用栈(二) 0 引言 程序的执行过程可看作连续的函数调用。当一个函数执行完毕时,程序要回到调用指令的下一条指令(紧接call指令)处继续执行。函数调用过程通常使用堆栈实现,每个用户态进程对应一个调用栈结构(call stack)。...
用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? ... Android 获取 View 宽高的常用正确方式,避免为零 - 掘金 相信有很多...
【哈斯娜伊】学习力六期预热D1 没遇到帅彭之前,自己也看了一部分育儿书籍,但是感觉看的越多越晕圈…尤其是在实际操作上很不得法,宝贝也提不起什么兴趣,正在一片迷茫,焦虑不安之际,一个很偶然的机会听到了彭彭的课,当时听完感觉这课讲的太生动了,太生活了,太棒了...
星期五下午,我们班级举办了《消防安全教育》的班级队会。 这次班会进展的很顺利。大家很开心!
在建工地 五一是完不了工了,看这进度估计国庆节也够呛。
在表面看来何其辛苦等现象,是以真的提升为前提的。所以不要为了辛苦累到自己感动自己而去辛苦,关键是质的提升。辛苦的付出是以完成伟大的计划为背景的,而只是过程有点辛苦而已。千万不要本末倒置,做到了表面文章,而里边是败絮。在导入文件的时候,Python只搜索当前脚本所在的目录,加载(entry-point)入口脚本运行目录和sys.path中包含的路径例如包的安装地址。所以如果要在当前脚本引用其他文件,除了将文件放在和脚本同一目录下,还有以下几种方法,
1. 将文件所在位置添加到sys.path中
import sys
sys.path.insert(0, '/path/to/application/app/folder') # or sys.path.append('/path/to/application/app/folder')
import file
2. 在文件目录下新建__init__.py文件然后调用文件
from application.app.folder.file import func_name
init.py文件
a).__init__.py文件的作用
该文件的主要作用使初始化Python包。如果目录下面包含了该文件,Python解释器就会将该目录当做一个包,下一步就可以使用import语句在别的.py脚本中引用该目录下的文件。一个标准Python模块的结构如下所示:
__init__.py
subpackage/
__init__.py
submodule1.py
submodule2.py
b). __init__文件可以为空但可以用来建立对包的需求。一般来说会在该文件中写那些类,函数等需要被导入到包水平,从而可以被方便的引用。比如:如果file.py文件中有一个File类,在init.py文件中啥都没写时引用File类需要这样操作:
from package.file import File
如果在__init__.py文件中将file导入包,那就在包水平可以直接引用File类:
# in your __init__.py
from file import File
# in your script
from package import File
此外,还需要注意的一点是__init__.py文件中的all变量。如果解释器在__init__.py文件中观察到了__all__变量,那么在运行from package import *时就只会引入__all__变量中列出的那些模块。例如:如果想在上述结构的只引入submodule1模块,那么可以在subpackage/__init__.py文件中定义__all__ = ['submodule1'],当引用subpackage时from subpackage import *就只引入了submodule1模块。
3. 将文件所在目录添加到python的环境变量
export PYTHONPATH=$HOME/pathToYourScripts/:$PYTHONPATH
阅读(...) 评论()C语言是编程语言的祖母,但是随着一代一代的编程语言长大,所以祖母也是会拍在沙滩上的,很多小小伙伴应该都会学过或者了解C语言,因为软件系的会教嘛,但是Pytho很多人都没学过,下面给大家介绍下,C语言和Python一起混合编程会产生什么不一样的火花吧!1、C/C++调用Python(基础篇)在Mac OS X 下的编译命令同上产生可执行文件后,直接运行,结果为输出Hello Python!Python库函数PyRun_SimpleString可以执行字符串形式的Python代码。虽然非常简单,但这段代码除了能用C语言动态生成一些Python代码之外,并没有什么用处。我们需要的是C语言的数据结构能够和Python交互。下面举个例子,比如说,有一天我们用Python写了一个功能特别强大的函数:从上述代码可以窥见Python内部运行的方式:所有Python元素,module、function、tuple、string等等,实际上都是PyObject。C语言里操纵它们,一律使用PyObject *。Python的类型与C语言类型可以相互转换。Python类型XXX转换为C语言类型YYY要使用PyXXXAsYYY函数;C类型YYY转换为Python类型XXX要使用PyXXXFromYYY函数。也可以创建Python类型的变量,使用PyXXX_New可以创建类型为XXX的变量。若a是Tuple,则a[i] = b对应于 PyTupleSetItem(a,i,b),有理由相信还有一个函数PyTupleGetItem完成取得某一项的值。不仅Python语言很优雅,Python的库函数API也非常优雅。现在我们得到了一个C语言的函数了,可以写一个main测试它编译的方式就用本节开头使用的方法。在Linux/Mac OSX运行此示例之前,可能先需要设置环境变量:bash:export PYTHONPATH=.:$PYTHONPATHcsh:setenv PYTHONPATH.:$PYTHONPATH2 Python 调用 C/C++(基础篇)这种做法称为Python扩展。比如说,我们有一个功能强大的C函数除了功能强大的函数great_function外,这个文件中还有以下部分:包裹函数greatfunction。它负责将Python的参数转化为C的参数(PyArgParseTuple),调用实际的greatfunction,并处理great_function的返回值,最终返回给Python环境。导出表GreateModuleMethods。它负责告诉Python这个模块里有哪些函数可以被Python调用。导出表的名字可以随便起,每一项有4个参数:第一个参数是提供给Python环境的函数名称,第二个参数是greatfunction,即包裹函数。第三个参数的含义是参数变长,第四个参数是一个说明性的字符串。导出表总是以{NULL, NULL, 0, NULL}结束。导出函数initgreat_module。这个的名字不是任取的,是你的module名称添加前缀init。导出函数中将模块名称与导出表进行连接。在Windows下面,在Visual Studio命令提示符下编译这个文件的命令是本部分参考资料《Python源码剖析-深度探索动态语言核心技术》是系统介绍CPython实现以及运行原理的优秀教程。Python 官方文档的这一章详细介绍了C/C++与Python的双向互动Extending and Embedding the Python Interpreter _ _关于编译环境,本文所述方法仅为出示原理所用。规范的方式如下:3. Building C and C++ Extensions with distutils _ _作为字典使用的官方参考文档Python/C API Reference Manual _ _3、C/C++调用Python(使用Cython)这其中有非Python关键字cdef和public。这些关键字属于Cython。由于我们需要在C语言中使用“编译好的Python代码”,所以得让great_function从外面变得可见,方法就以“public”修饰。而cdef类似于Python的def,只有使用cdef才可以使用Cython的关键字public。这个函数中其他的部分与正常的Python代码是一样的。接下来编译 great_module.pyx编译命令和第一部分相同:在Windows下编译命令为在Visual Studio命令提示符下编译:cl/LD dllmain.cgreat_module.c-IC:Python27includeC:Python27libspython27.lib会得到一个dllmain.dll。我们在Excel里面使用它,没错,传说中的Excel与Python混合编程:参考资料:Cython的官方文档4、Python调用C/C++(使用SWIG)接下来使用SWIG将这个配置文件编译为所谓Python Module Wrapperswig-python mymodule.i得到一个 mymodule_wrap.c和一个mymodule.py。把它编译为Python扩展:Windows:cl/LD mymodule_wrap.c/o_mymodule.pyd-IC:Python27includeC:Python27libspython27.libLinux:gcc-fPIC-shared mymodule_wrap.c-o_mymodule.so-I/usr/include/python2.7/-lpython2.7注意输出文件名前面要加一个下划线。现在可以立即在Python下使用这个module了:换句话说,SWIG自动完成了诸如Python类型转换、module初始化、导出代码表生成的诸多工作。对于C++,SWIG也可以应对。例如以下代码有C++类的定义:写在最后:由于CPython自身的结构设计合理,使得Python的C/C++扩展非常容易。如果打算快速完成任务,Cython(C/C++调用Python)和SWIG(Python调用C/C++)是很不错的选择。但是,一旦涉及到比较复杂的转换任务,无论是继续使用Cython还是SWIG,仍然需要学习Python源代码。文章整理自网络,侵删。免费活动直播预约▼ 责任编辑:
周一至周日 9:00-18:00(全国免费咨询)
您正在使用移动设备访问,是否切换到手机版?
欢迎访问APISTORE
免费试用,在线咨询
工作时间:& 9:00-24:00}

我要回帖

更多关于 调用.py 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信