在python代码中,写其他编程语言的hello world
1. hello world不论哪种编程语言,在你最开始学习时,都会给你一个在终端输出hello world的示例print("hello world")这已经成为一种惯例,最近在github上闲逛时,偶遇了一个特别有趣的项目,这个作者实现了一个模块,可以让你在python代码里,使用其他编程语言的语法和关键字来编写hello world , 就像下面这样import anyprintprintf
1. hello world
不论哪种编程语言,在你最开始学习时,都会给你一个在终端输出hello world的示例
print("hello world")
这已经成为一种惯例,最近在github上闲逛时,偶遇了一个特别有趣的项目,这个作者实现了一个模块,可以让你在python代码里,使用其他编程语言的语法和关键字来编写hello world , 就像下面这样
import anyprint
printf("printf %d\n", 10) # c
fmt.Println("hello") # go
cout << "Hello, C++!" << endl # c++
这个项目的github地址是: https://github.com/kragniz/anyprint , 源码只有不到200行,真正核心的代码也只有20行。
2. 实现原理
刚看到这个库时,从它的示例代码中,我已经大致猜出了它的实现原理。
printf并不是python中的关键字,直接使用一定会报错的。这个函数一定是在anyprint 模块里实现了,但作者只是将anyprint引入(import anyprint ),而不是从anyprint模块里引入printf (from anyprint import printf),这说明,在anyprint模块里,已经将printf写入到内置作用域。
打开anyprint.py文件,在文件末尾有如下代码
def make_module(name, members):
m = types.ModuleType(name)
m.__name__ = name
for k, v in members.items():
if type(v) is dict:
m.__dict__[k] = make_module(k, v)
else:
m.__dict__[k] = v
return m
for k, v in prints.items():
if type(v) is dict:
globals()['__builtins__'][k] = make_module(k, v)
else:
globals()['__builtins__'][k] = v
globals函数以字典的形式返回全局作用域的变量,__builtins__ 所对应的value就是内置作用域模块,prints是一个字典,内容如下
prints = {
# go
'fmt': {
'Println': print,
'Printf': printf,
'Print': printn,
},
# java
'System': {
'out': {
'println': print,
'printf': printf,
},
# Visual Basic .NET
'Console': {
'Write': printn,
'WriteLine': print,
},
},
# kotlin
'println': print,
# C like
'printf': printf,
}
我以printf和fmt 为例,解释它如何工作的。在遍历prints时,如果key为printf,value是一个函数
printf = lambda *args: print(args[0] % args[1:], end='')
则执行
globals()['__builtins__'][k] = v # 写入内置作用域
当你在脚本里使用printf时,如果局部作用域,内嵌作用域,全局作用域都找不到printf,则会去内置作用域里查找,而当前时刻,内置作用域里确实有pirntf,这个printf函数可以通过globals()[‘builtins’][‘printf’]获取到。
遍历prints时,如果key是fmt, 其value是一个字典,则执行
m.__dict__[k] = make_module(k, v)
我们来看make_module的实现
def make_module(name, members):
m = types.ModuleType(name)
m.__name__ = name
for k, v in members.items():
if type(v) is dict:
m.__dict__[k] = make_module(k, v)
else:
m.__dict__[k] = v
return m
函数首先会创建出一个名为fmt的模块,这个模块会被写入到内置模块,这样,就可以直接使用fmt了,fmt模块里,还有3个方法
{
'Println': print,
'Printf': printf,
'Print': printn,
}
再次进行遍历,将Println,Printf, Print 写入模块m的__dict__字典中,value就是事先准备好的print, printf, printn 函数,这样当你在代码里执行
fmt.Println("hello")
首先在内置模块里找到fmt模块,然后在fmt模块的__dict__字典中找到Println函数来执行。
再来看java部分的实现
'System': {
'out': {
'println': print,
'printf': printf,
},
# Visual Basic .NET
'Console': {
'Write': printn,
'WriteLine': print,
},
},
嵌套层级更深,但原理是一样的,创建一个名为System的模块,写入内置作用域,在System的__dict__字典里有一个名为out的模块,在out模块的__dict__字典里有一个println函数。
作者巧妙的利用了python的内置作用域,或是直接将函数写入内置作用域,或是创建相应的模块供用户使用。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)