我想禁止在函数中使用某些运算符,例如,我想确保**
幂运算符未在以下函数中使用:
def pow(x, y):
return x ** y
我已使用inspect.getsource
获取源代码并检查源"**"
是否在源中但如果源中的"**"
恰好位于其他位置,则会错误地导致断言错误如何实际检查代码是否存在特定的运算符?
答案 0 :(得分:9)
如果你手头有3.4,我个人会去找Ashwini的答案,但是,如果你需要更多兼容并且不介意解析源代码,那么你可以使用ast
,例如:
import inspect
import ast
def pow(x, y):
return x ** y
nodes = ast.walk(ast.parse(inspect.getsource(pow)))
has_power = any(isinstance(node, ast.Pow) for node in nodes)
答案 1 :(得分:5)
注意:我们在这里处理的字节代码是CPython实现细节。不要指望它可以用于其他Python实现。首选Jon Clements's approach。
在CPython 3.4+中,您可以使用dis.get_instructions
检查函数的代码对象中是否存在BINARY_POWER
指令(在What's new in Python 3.4 doc中也有解释):
>>> import dis
>>> def search_instruction(code_object, instr_code):
for ins in dis.get_instructions(code_object):
if ins.opcode == instr_code:
return True
return False
...
>>> def f1():
s = x ** 2
...
>>> def f2():
s = 'x ** 2'
...
>>> dis.opmap['BINARY_POWER']
19
>>> search_instruction(f1.__code__, 19)
True
>>> search_instruction(f2.__code__, 19)
False
对于CPython 2.X,你可以尝试在PyPI上使用byteplay
包(它的Python 3 fork:https://github.com/serprex/byteplay)。:
>>> import byteplay
>>> def search_instruction(code_object, instr_code):
for ins, _ in byteplay.Code.from_code(code_object).code:
if ins == instr_code:
return True
return False
...
>>> search_instruction(f1.__code__, 19)
True
>>> search_instruction(f2.__code__, 19)
False
相关:Bytecode: What, Why, and How to Hack it - Dr. Ryan F Kelly
答案 2 :(得分:1)
也许使用dis模块?:
In [9]: dis.dis(pow)
2 0 LOAD_FAST 0 (x)
3 LOAD_FAST 1 (y)
6 BINARY_POWER
7 RETURN_VALUE
您可能需要redirect stdout to a stringIO在Python< 3.4
中解析它