模拟pragma编译器指令的python代码转换器

pragma的Python项目详细描述


…图片::https://travis-ci.org/scnerd/pypragma.svg?branch=master
:目标:https://travis ci.org/scnerd/pypragma

…图片::https://coveralls.io/repos/github/scnerd/pypragma/badge.svg?branch=master
:目标:https://coveralls.io/github/scnerd/pypragma?分支=主

…图片::https://readthedocs.org/projects/pypragma/badge/?version=latest
:目标:http://pypragma.readthedocs.io/en/latest/?badge=latest
:alt:documentation status


overview
=


pypragma是一组用于执行就地代码修改的工具,受c中编译器指令的启发。这些修改旨在不对代码的执行进行功能更改。在C语言中,这用于提高代码性能或进行某些折衷(通常在二进制文件的大小与其执行速度之间)。在python中,当利用不允许使用某些python特性的代码生成库(如numba或tangent)时,这些更改最适用。通过就地转换代码,不允许的特性可以在运行时转换为允许的语法,而不牺牲python代码的动态特性。

例如,使用numba,不可能编译动态引用和调用其他函数(例如,不能从列表中选择一个函数然后执行它,只能通过函数的显式名称调用函数::


@numba.jit
def call(i,x):
return fns[i](x)不允许,由于不知道要调用哪个函数,如果在定义函数时动态是静态的,比如在本例中,那么可以将这些动态语言特性展平为更简单的特性,这样代码生成库就更可能支持这些特性(例如,该函数可以被提取到闭包变量中,然后直接使用该名称调用::


fns_1=fns[1]
fns_2=fns[2]

@numba.jit
def call(i,x):
如果i==0:
return fns_0(x)
如果i==1:
返回fns_1(x)
如果i==2:
返回fns_2(x)

只有当动态特性在*运行前已知时,即如果动态计算了``fns`,程序员才能进行这种修改,然后,程序员无法执行此修改,即使此示例演示了原始函数不是固有的动态函数,但它看起来就是这样。pypragma在运行时启用这个转换,对于这个示例函数来说,它看起来像::


@numba.jit
@pragma.deindex(fns,'fns')
@pragma.unroll(num fns=len(fns))
def call(i,x):
for j in range(num fns):
如果i==j:
返回fns[j](x)仍然是动态调用,但decorators转换为静态的

此示例将在本地和运行时转换为上面完全展开的代码。




installation
=您可以选择从pypi安装::


或者直接从github安装::




在不更改其执行行为的情况下就地执行函数。它们可以这样导入:

import pragma

或者作为函数调用:

@pragma.unroll
def pows(i):
x in range(3):
yield i**x


pows(5)

pragma.unroll(pows)(5)

/>
def pows(i):
yield i**0
yield i**1
yield i**2


pows(5)

任何未指定的关键字参数都将作为变量添加到结果函数的闭包中。此外,修饰函数的闭包被保留,因此还包括外部变量。举个简单的例子,上面的代码也可以写成:

@pragma.unroll(num-pows=3)
def-pows(i):
x in-range(num-pows):
yield i**x

或者……

num-pows=3
@pragma.unroll
def-pows(i):
x in-range(num-pows):
yield i**x

当然,某些关键字是保留的,这将在每个装饰器的文档中定义。另外,生成的函数是一个实际的、正确的python函数,因此必须遵循python语法规则。因此,某些修改依赖于使用某些变量名,这可能会与函数使用的其他变量名冲突。已经尽一切努力通过使用损坏的变量名来避免这种情况,但冲突的可能性仍然存在。

python语法的一个副作用是,函数可以通过任何正常的pythonic反射来检索其源代码:

in[1]:@pragma.unroll(num_pows=3)
…:def pows(i):
…:对于x in射程(单位威力):
…:在[2]中产生i**x
…:


签名:pows(i)
源:
def pows(i):
yield i**0
yield i**1
yield i**2
文件:/tmp/tmpmn5bza2j
类型:函数

作为一个实用程序,主要用于测试和调试,通过使用"return-source=true"参数,可以很容易地从每个decorator*而不是转换函数中检索源代码。


`:

在[1]中:@pragma.collapse撸u literals(x=5)
…:def f(y):
…:z=x//2
…:return y*10**z
…:


签名:f(y)
源:
def(y):
z=2
返回y*100

de index arrays
++++++++'fns')
…:def调用(i,x):
…:如果i==0:
…:返回fns[0](x)
…:如果i==1:
…:返回fns[1](x)
…:如果i==2:
…:返回fns[2](x)
…:


签名:调用(i,x)
源:
定义调用(i,x):
如果i==0:
返回fns_0(x)
如果i==1:
返回fns_1(x)
如果i==2:
返回fns_2(x)

请注意,虽然从上面打印的源代码中看不出来,但每个变量"fns_x"在修饰发生时都被赋给了"fns[x]`的值:

[4]:call(0,math.pi)
out[4]:1.2246467991473532e-16,s in(pi)=0

[5]:call(1,math.pi)
出[5]:-1.0又名,cos(pi)=-1

-1]

在[2]:@pragma.unroll
…:def f(x):
…:对于范围(3)中的j:
…:对于登录p\u或m:
…:yield sign*(x+j)
…:



签名:f(x)
来源:
定义f(x):
收益率1*(x+0)
收益率-1*(x+0)
yield 1*(x+1)
收益率-1*(x+1)
收益率1*(x+2)
收益率-1*(x+2)


`:

[1]:def sqr(x):
…:返回x**2
…:

[2]:@pragma.inline(sqr)
…:def sqr u sum(a,b):
…:返回sqr(a)+sqr(b)
…:

[3]:sqr u sum??
签名:sqr_sum(a,b)
源:
定义sqr_sum(a,b):
sqr_0=dict(x=a)准备"sqr(a)"
准备"无"中的"sqr(a)":"块中的wrap函数
"u sqr_0['return']="u sqr_0['x']**2"计算返回值
"break""return"
"u sqr_0=\u sqr_0.get('return',无)提取返回值
del sqr_u 0删除参数字典,函数调用完成
u sqr_u 0=dict(x=b)誠对[无]中的'sqr(b)
执行相同的操作:
u sqr_u 0['return']="u sqr_u 0['x']**2
break
_ sqr_return_1=_sqr_0.get('return',none)
del_sqr_0
return_sqr_return_0+_sqr_return_1>替换函数调用的返回值

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java确保我正确地解决了这个问题   对于Java接口中的常量,“publicstaticfinal”是多余的吗?   为什么是java。网SocketException:socket在java之后关闭。网ConnectException:连接被拒绝'?   安卓在Java中将JSON转换为多维数组的最佳方式是什么?   java如何为gradle构建使用lint4j插件,以及如何为Jenkins配置它?   JavaMaven:一个项目如何能够从一个二级依赖引用一个类   使用java的excel Linest函数   java如何完全禁用JTextPane的文本突出显示?   java jBoss概要如何?   java Pi4J类路径错误Intellij在Pi Zero W上远程运行   java如何根据特定条件在JPA/Play中使用EntityManager进行批量更新?   java如何在EJB调度中设置计时器值?   javasocket服务器没有连接   java如何在日期解析后以yyyyMMdd格式获取日期对象   java客户端python服务器发送udp数据   使用ArrayList从java文件中读取文本   框架上的java Selenium测试   java setOnClickListener匿名类?