有没有办法在 Python 中漂亮地打印 Lisp 样式的代码字符串(换句话说,一堆平衡的括号和文本)而不重新发明轮子?
2 回答
简短的回答
如果可以的话,我认为一种合理的方法是生成 Python 列表或自定义对象而不是字符串并使用pprint模块,正如@saulspatz 所建议的那样。
长答案
整个问题看起来像是XY-problem的一个实例。为什么?因为您正在使用Python(为什么不使用 Lisp?)来操作表示生成的 Lisp 样式代码的字符串(为什么不使用数据结构?) ,其中Lisp 样式被定义为“一堆括号和其中的文本”。对于“如何漂亮打印?”的问题,我会回答“我不会从这里开始!” . 除了使用现有的轮子之外,在您的情况下不重新发明轮子的最佳方法是坚持简单的输出格式。
但首先,你为什么需要漂亮的打印?谁会查看生成的代码?
根据您使用的确切 Lisp 方言和代码的预期用途,您可以非常不同地格式化您的代码。例如,考虑文本的换行符、缩进和最大宽度。Common Lisp 漂亮的打印机是特别进化的,我怀疑你是否想要拥有相同级别的可配置性。如果你使用 Lisp,一个简单的调用就pprint
可以解决你的问题,但是你使用的是 Python,所以暂时坚持最合理的输出,因为漂亮的打印是一罐蠕虫。
如果您的代码是供人类读者使用的,请:
- 不要把右括号放在自己的行上
- 不要垂直对齐左括号和右括号
- 不要在左括号之间添加空格
这很丑:
( * ( + 3 x )
(f
x
y
)
)
这个更好:
(* (+ 3 x)
(f x y))
或者简单地说:
(* (+ 3 x) (f x y))
但在打印之前,您必须解析输入字符串并确保其格式正确。由于您生成表单的方式,也许您确定它格式正确,但我认为打印机应该忽略这一点并且不要做出太多假设。如果您向漂亮的打印机传递一个由 Python 对象表示的 AST,而不仅仅是字符串,这会更容易,正如评论中所建议的那样。您可以构建数据结构或自定义类并使用pprint (python) 模块。如上所述,如果您可以更改生成 Lisp 样式代码的方式,这似乎是您的情况。
使用字符串,您应该处理任何可能的输入并拒绝无效的输入。这意味着检查括号和引号是否平衡(注意转义字符)等。实际上,您不需要真正构建用于打印的中间树(尽管它可能对您程序的其他部分有所帮助),因为 Lisp-样式代码由易于嵌套并使用前缀表示法的形式组成:您可以从左到右扫描输入字符串,并在看到括号时根据需要打印(开括号:递归;右括号,从递归返回)。当您第一次遇到未转义的双引号"
时,请阅读直到下一个"
,... 这再加上简单的打印方法,足以满足您的需求。
我认为最简单的方法是使用三引号。如果你说:
print """
(((This is some lisp code))) """
它应该工作。您可以在三引号内以任何您喜欢的方式格式化您的代码,它会以您想要的方式出现。
祝你好运,编码愉快!