在python代码中,写其他编程语言的hello world

本文介绍了anyprint模块的工作原理,该模块允许在Python中使用其他编程语言的语法,如C、Go和Java。通过将特定函数写入内置作用域或创建模块,anyprint实现了在Python中调用类似`printf`、`fmt.Println`等其他语言的函数。作者巧妙地利用了Python的内置作用域机制,使得代码能够识别并执行这些非Python的语法结构。
摘要由CSDN通过智能技术生成

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的内置作用域,或是直接将函数写入内置作用域,或是创建相应的模块供用户使用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷python

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值