python - 如何向 Python 添加阅读器宏?

标签 python

背景

在 Verilog 中,我可以使用包含下划线的表达式来指定二进制数。例如:

12'b1100_0111_0001 == 12'b110001110001  // The underscores are ignored

我发现这是一个很好的特性,并想将它添加到 Python 中,这样我就可以编写如下内容:

x = 0b1100_0111_0001
y = 0x3fff_cc00

在 Lisp 中,我可以使用 set-dispatch-macro-character 之类的东西来做到这一点,以便能够在通过阅读器宏编译源代码之前对其进行编辑。

问题

在 Python 中添加类似 Lisp 的阅读器宏的好方法是什么?

对于用我当前的方法或完全不同的方法解决问题的建议,我同样会很高兴。

我尝试过的

我已尝试将自定义查找器对象添加到 sys.meta_path。这几乎可以工作,除了两个问题:

  1. 当我使用自定义查找器导入模块时,它不存储文件的 pyc 编译表示
  2. 理想情况下,我希望阅读器宏应用于顶层文件的其余部分,而不是必须将我的代码放入单独的文件“verilog_test_code.py”

源代码

verilog_test_code.py

def run_test():
    return 0b1100_0111_0001+0x3fff_cc00

toplevel.py

import remove_underscores
import verilog_test_code
print verilog_test_code.run_test()

remove_underscores.py

import tokenize,sys,imp

def remove_underscores(src):
    """Remove underscores from hexadecimals."""
    result = []
    g = tokenize.generate_tokens(src.readline)   
    for toknum, tokval, _, _, _  in g:
        if toknum == tokenize.NAME and tokval[0]=='_' and result and result[-1][0]==tokenize.NUMBER:
            result[-1][1] = str(result[-1][1]) + tokval[1:].replace('_','')
        else:
            result.append([toknum, tokval])
    return tokenize.untokenize(result)


class my_finder_loader(object):

    def is_package(self, fullname):
        return False

    def get_code(self, fullname):
        return compile(self.get_source(fullname),fullname,'exec')

    def get_source(self, fullname):
        (src, pathname, description) = imp.find_module(fullname)
        srctext = remove_underscores(src)
        src.close()
        return srctext

    def load_module(self, fullname):
        if fullname in sys.modules:
            return sys.modules[fullname]
        code = self.get_code(fullname)
        mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
        mod.__file__ = "<%s>" % self.__class__.__name__
        mod.__loader__ = self
        mod.__package__ = ''
        exec(code, mod.__dict__)
        return mod

    def find_module(self, fullname, path=None): 
        if not fullname.startswith('verilog_'):
            return None
        return self

sys.meta_path.append(my_finder_loader())

最佳答案

class BinaryUnderscorifier(object):

    def __getattr__(self, name):
        return int(name.replace('_', ''), 2)

b = BinaryUnderscorifier()

print b._1100_0111_0001 == 0b110001110001       # prints "True"

当然,b._1100_0111_0001的反汇编与0b110001110001的反汇编有很大不同,可能是例如对你来说是一个性能打击,但希望不会。

关于python - 如何向 Python 添加阅读器宏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21945719/

相关文章:

python - 如何检查数字溢出而不在 Python 中收到警告?

python - 二叉树的高度

python - 如何在 python 中使用 mechanize 发送带有 post 请求的原始 JSON 数据

python - Paypal 自适应支付 589023

python - 为什么 Python 会创建不必要的不​​可变对象副本?

python - 如何通过 easy-install 安装特定版本的 pip? - Mac OS 小牛队

python - 非矩形域上的 3D 图

python - 无法在 python 中使用 plotly 进行绘图

具有列表本地和全局范围的 Python 奇怪的东西

python - 多处理池 - 如果返回所需结果,如何取消所有正在运行的进程?