我想禁止在函数中使用某些运算符,例如,我想确保**在以下函数中不使用幂运算符:
def pow(x, y):
return x ** y
Run Code Online (Sandbox Code Playgroud)
我已经习惯inspect.getsource了获取源代码并检查是否"**"在源代码中但是如果"**"在其他地方的源代码中恰好存在断言错误,那么如何实际检查代码是否存在特定的运算符?
如果你手头有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)
Run Code Online (Sandbox Code Playgroud)
注意:我们在这里处理的字节代码是CPython实现细节.不要指望它可以用于其他Python实现.更喜欢Jon Clements的方法.
在CPython 3.4+中,你可以dis.get_instructions用来检查BINARY_POWER函数的代码对象中是否存在指令(在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
Run Code Online (Sandbox Code Playgroud)
对于CPython 2.X,你可以尝试byteplay在PyPI上使用它的包(它的Python 3分支: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
Run Code Online (Sandbox Code Playgroud)
相关:字节代码:什么,为什么以及如何破解它 - Ryan F Kelly博士