模拟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>替换函数调用的返回值
:目标: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_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>替换函数调用的返回值