检查函数中是否使用了某些运算符

时间:2014-09-16 19:55:00

标签: python operators

我想禁止在函数中使用某些运算符,例如,我想确保**幂运算符未在以下函数中使用:

def pow(x, y):
    return x ** y

我已使用inspect.getsource获取源代码并检查源"**"是否在源中但如果源中的"**"恰好位于其他位置,则会错误地导致断言错误如何实际检查代码是否存在特定的运算符?

3 个答案:

答案 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

中解析它