不是争论,只是探讨,和编辑器无关。
我理解像这个 spy
这样的东西在 Python 里面是无法实现。从编程者角度讲还是有意义的。
def spy(x):
print(f"{x} => {eval(x)}")
spy("1 + 2")
# 1 + 2 => 3
這樣?
这个我觉得还是有些区别的。
def spy(x):
print(f"{x} => {eval(x)}")
def foo():
x = 1
spy("1 + x")
foo()
import inspect
def spy(fn):
def spyprint(*args):
print(inspect.getsource(fn) + "->")
print(fn(*args))
return spyprint
@spy
def useful(a,b):
return a*b
useful(2,5)
也是可以的,實際上 Python 是可以這樣的
c = compile("1 + x", filename="", mode="eval")
x = 1
eval(c) # 2
这里实际上 2 和 5 这两个参数的信息都丢失了。
要怎么把这个和之前的 spy 组合起来呢?
2 和 5 是啥 哦明白了我改改
这个 spy 的关键是在于把参数的表达式给打印出来了。
x = 2
y = spy(x + 5)
# x + 5 => 7
需要的效果是这样的。
上面那个截图整理下打印格式你觉得满足要求么
不,不是这样的。你看换成 useful(x, 5)
时打印的应该是 x, 5
那没办法,你要的是打印编译期间的东西,py 只能包在 lambda 里面阻止它执行才能达到类似效果。
你是强行要求 spy 必须是个看起来和函数差不多的东西,但是 py 语法没有像 lisp 那么统一,它写不成函数那个样子,就只能写 @,@ 就可以拿原函数的 metadata 然后做处理,功能其实和宏是有重叠的。
decorator 也只是高阶函数,我理解的 Python 里面应该是写不出来类宏的东西。也许有人知道怎么做才可以,比较好奇。
還是可以的,但是你得手動用 ast 包調整,把整個 parse 進去後,改 ast 就行。
我没有用过 ast 包,但是似乎
宏能实现的功能在别的语言里面都是拆改成很多分散的替代品。比如你这个通过宏获取函数的源码和参数信息,那别的语言就用反射实现。
反射对应的是运行时,但是运行时的信息是已经有折损的了,一个叫 foo 的函数在运行时中未必还留有 foo 这个名字。
運行時損耗沒辦法,但可以不用字符串
你可以用 inspect.getsource 來得到源代碼,然後 ast.parse 得到 ast,然後修改再 eval
所以宏和反射只是功能有重叠。就比如 Java,反射很强但是写一些类似 lombok 的功能还是得手撸 AST。