Python ast 模块,Compare() 实例源码
我们从Python开源项目中,提取了以下50个代码示例,用于说明如何使用ast.Compare()。
def __init__(self, expr, context):
self.expr = expr
self.context = context
self.expr_table = {
LLLnode: self.get_expr,
ast.Num: self.number,
ast.Str: self.string,
ast.NameConstant: self.constants,
ast.Name: self.variables,
ast.Attribute: self.attribute,
ast.Subscript: self.subscript,
ast.Binop: self.arithmetic,
ast.Compare: self.compare,
ast.BoolOp: self.boolean_operations,
ast.UnaryOp: self.unary_operations,
ast.Call: self.call,
ast.List: self.list_literals,
ast.Dict: self.struct_literals,
ast.Tuple: self.tuple_literals,
}
expr_type = self.expr.__class__
if expr_type in self.expr_table:
self.lll_node = self.expr_table[expr_type]()
else:
raise Exception("Unsupported operator: %r" % ast.dump(self.expr))
def simplify_multicomp(a):
if type(a) == ast.Compare and len(a.ops) > 1:
# Only do one comparator at a time. If we don't do this,things get messy!
comps = [a.left] + a.comparators
values = [ ]
# Compare each of the pairs
for i in range(len(a.ops)):
if i > 0:
# Label all nodes as middle parts so we can recognize them later
assignPropertyToAll(comps[i], "multiCompMiddle")
values.append(ast.Compare(comps[i], [a.ops[i]], [deepcopy(comps[i+1])], multiCompPart=True))
# Combine comparisons with and operators
boolOp = ast.And(multiCompOp=True)
boolopVal = ast.BoolOp(boolOp, values, multiComp=True, global_id=a.global_id)
return boolopVal
return a
def visit_If(self, node):
"""
If(expr test,stmt* body,stmt* orelse)
"""
if isinstance(node.test, (ast.NameConstant, ast.Compare)):
self.write("if %s" % self.visit(node.test))
else:
self.write("if is_bool(%s)" % self.visit(node.test))
self.indent()
for stmt in node.body:
self.visit(stmt)
self.dedent()
if node.orelse:
self.write("else")
self.indent()
for stmt in node.orelse:
self.visit(stmt)
self.dedent()
self.write("end")
def visit_UnaryOp(self, node):
if not self.config.constant_folding:
return
eval_unaryop = EVAL_UNARYOP.get(node.op.__class__)
if eval_unaryop is None:
return
if isinstance(node.op, ast.Invert):
types = int
else:
types = COMPLEX_TYPES
value = get_constant(node.operand, types=types)
if value is not UNSET:
result = eval_unaryop(value)
return self.new_constant(node, result)
if (isinstance(node.op, ast.Not)
and isinstance(node.operand, ast.Compare)):
new_node = self.not_compare(node)
if new_node is not None:
return new_node
def visit_Compare(self, node, **kwargs):
ops = node.ops
comps = node.comparators
# base case: we have something like a CMP b
if len(comps) == 1:
op = self.translate_In(ops[0])
binop = ast.Binop(op=op, left=node.left, right=comps[0])
return self.visit(binop)
# recursive case: we have a chained comparison,a CMP b CMP c,etc.
left = node.left
values = []
for op, comp in zip(ops, comps):
new_node = self.visit(ast.Compare(comparators=[comp], left=left,
ops=[self.translate_In(op)]))
left = comp
values.append(new_node)
return self.visit(ast.BoolOp(op=ast.And(), values=values))
def make_op_name_dict(self):
'''
Make a dict whose keys are operators ('+','+=',etc),
and whose values are lists of values of ast.Node.__class__.__name__.
'''
d = {
'.': ['Attr',],
'(*)': ['Call', 'Tuple',
'[*]': ['List', 'Subscript',
'{*}': ['???',
### 'and': 'BoolOp',
### 'or': 'BoolOp',
}
for op in (
'+', '-', '*', '/', '%', '**', '<<',
'>>', '|', '^', '&', '//',
):
d[op] = ['Binop',]
for op in (
'==', '!=', '<', '<=', '>', '>=',
'is', 'is not', 'in', 'not in',
):
d[op] = ['Compare',]
return d
def make_switch_group(if_node, parent_case):
cases_ast = u.if_and_or_else_blocks(if_node)
switch_group = SwitchGroup(None, parent_case.num_switch_groups())
switch_group.set_parent_case(parent_case)
switch_group.var_name = None
for if_node in cases_ast:
compare_node = u.cast(if_node.test, ast.Compare)
var_name, val = u.parse_compare(compare_node)
if switch_group.var_name is None:
switch_group.var_name = var_name
else:
assert var_name == switch_group.var_name, "if blocks must switch on same var"
case_node = make_case_node(if_node.body, var_name, val)
switch_group.add_case(val, case_node)
return switch_group
def normalize_compare(node):
"""Rewrites a compare expression to a `and` expression
1 < 2 < 3 > 0
1 < 2 and 2 < 3 and 3 > 0"""
and_values = []
left = node.left
for (op, val) in zip(node.ops, node.comparators):
comp = ast.Compare(ops=[op],
left=left,
comparators=[val],
lineno=node.lineno,
col_offset=node.col_offset)
and_values.append(comp)
left = val
return ast.BoolOp(op=ast.And(),
values=and_values,
lineno=node.lineno,
col_offset=node.col_offset)
def translate_pat_Call_constructor(self, ctx, pat, scrutinee_trans):
lbl = pat.func.id
tag_loc = ast.Subscript(
value=scrutinee_trans,
slice=ast.Index(value=ast.Num(n=0)))
lbl_condition = ast.Compare(
left=tag_loc,
ops=[ast.Eq()],
comparators=[ast.Str(s=lbl)])
arg = pat.args[0]
arg_scrutinee = ast.Subscript(
value=scrutinee_trans,
slice=ast.Index(value=ast.Num(n=1)))
arg_condition, binding_translations = ctx.translate_pat(arg, arg_scrutinee)
condition = ast.BoolOp(
op=ast.And(),
values=[lbl_condition, arg_condition])
return condition, binding_translations
def visit_Name(self, name):
# display the repr of the name if it's a local variable or
# _should_repr_global_name() thinks it's acceptable.
locs = ast_Call(self.builtin("locals"), [], [])
inlocs = ast.Compare(ast.Str(name.id), [ast.In()], [locs])
dorepr = self.helper("should_repr_global_name", name)
test = ast.BoolOp(ast.Or(), [inlocs, dorepr])
expr = ast.IfExp(test, self.display(name), ast.Str(name.id))
return name, self.explanation_param(expr)
def visit_Compare(self, comp):
self.push_format_context()
left_res, left_expl = self.visit(comp.left)
if isinstance(comp.left, (_ast.Compare, _ast.BoolOp)):
left_expl = "({0})".format(left_expl)
res_variables = [self.variable() for i in range(len(comp.ops))]
load_names = [ast.Name(v, ast.Load()) for v in res_variables]
store_names = [ast.Name(v, ast.Store()) for v in res_variables]
it = zip(range(len(comp.ops)), comp.ops, comp.comparators)
expls = []
syms = []
results = [left_res]
for i, op, next_operand in it:
next_res, next_expl = self.visit(next_operand)
if isinstance(next_operand, _ast.BoolOp)):
next_expl = "({0})".format(next_expl)
results.append(next_res)
sym = binop_map[op.__class__]
syms.append(ast.Str(sym))
expl = "%s %s %s" % (left_expl, sym, next_expl)
expls.append(ast.Str(expl))
res_expr = ast.Compare(left_res, [op], [next_res])
self.statements.append(ast.Assign([store_names[i]], res_expr))
left_res, left_expl = next_res, next_expl
# Use pytest.assertion.util._reprcompare if that's available.
expl_call = self.helper("call_reprcompare",
ast.Tuple(syms, ast.Load()),
ast.Tuple(load_names,
ast.Tuple(expls,
ast.Tuple(results, ast.Load()))
if len(comp.ops) > 1:
res = ast.BoolOp(ast.And(), load_names)
else:
res = load_names[0]
return res, self.explanation_param(self.pop_format_context(expl_call))
def cleanupEquals(a):
"""Gets rid of silly blah == True statements that students make"""
if not isinstance(a, ast.AST):
return a
if type(a) == ast.Call:
a.func = cleanupEquals(a.func)
for i in range(len(a.args)):
# But test expressions don't carry through to function arguments
a.args[i] = cleanupEquals(a.args[i])
return a
elif type(a) == ast.Compare and type(a.ops[0]) in [ast.Eq, ast.NotEq]:
l = a.left = cleanupEquals(a.left)
r = cleanupEquals(a.comparators[0])
a.comparators = [r]
if type(l) == ast.NameConstant and l.value in [True, False]:
(l,r) = (r,l)
# If we have (boolean expression) == True
if type(r) == ast.NameConstant and r.value in [True, False] and (eventualType(l) == bool):
# Matching types
if (type(a.ops[0]) == ast.Eq and r.value == True) or \
(type(a.ops[0]) == ast.NotEq and r.value == False):
transferMetaData(a, l) # make sure to keep the original location
return l
else:
tmp = ast.UnaryOp(ast.Not(addednotOp=True), l)
transferMetaData(a, tmp)
return tmp
else:
return a
else:
return applytochildren(a, cleanupEquals)
def visit_IfExp(self, node):
"""
IfExp(expr test,expr body,expr orelse)
"""
body = self.visit(node.body)
or_else = self.visit(node.orelse)
if isinstance(node.test, ast.Compare)):
return "(%s) ? %s : %s" % (self.visit(node.test), body, or_else)
else:
return "is_bool(%s) ? %s : %s" % (self.visit(node.test), or_else)
def visit_Compare(self, node):
"""
Compare(expr left,cmpoP* ops,expr* comparators)
"""
assert len(node.ops) == len(node.comparators)
def compare_pair(left, comp, op):
if (left == '__name__') and (comp == '"__main__"') or \
(left == '"__main__"') and (comp == '__name__'):
""" <Python> __name__ == '__main__':
<Ruby> __FILE__ == $0 """
left = '__FILE__'
comp = '$0'
if isinstance(op, ast.In):
return "%s.include?(%s)" % (comp, left)
elif isinstance(op, ast.notin):
return "!%s.include?(%s)" % (comp, ast.Eq):
return "%s == %s" % (left, comp)
elif isinstance(op, ast.NotEq):
return "%s != %s" % (left, ast.IsNot):
return "!%s.equal?(%s)" % (left, comp)
else:
return "%s %s %s" % (left, self.get_comparison_op(op), comp)
compare_list = []
for i in range(len(node.ops)):
if i == 0:
left = self.visit(node.left)
else:
left = comp
comp = self.visit(node.comparators[i])
op = node.ops[i]
pair = compare_pair(left, op)
if len(node.ops) == 1:
return pair
compare_list.append('(' + pair + ')')
return ' and '.join(compare_list)
# python 3
def _binop(self, other, *, _opnode=opnode, _sym=sym):
othername, constants = _normalize_arg(
other,
self._constants,
)
return __class__(
'%s %s %s' % (self._pname, _sym, othername),
ast.Compare(
left=self._tree,
ops=[_opnode()],
comparators=[other],
),
merge(constants, getattr(other, '_constants', {})),
)
def visit_Assert(self, node):
if isinstance(node.test, ast.Compare) and \
len(node.test.ops) == 1 and \
isinstance(node.test.ops[0], ast.Eq):
call = ast.Call(func=ast.Name(id='assert_equal', ctx=ast.Load()),
args=[node.test.left, node.test.comparators[0]],
keywords=[])
# Wrap the call in an Expr node,because the return value isn't used.
newnode = ast.Expr(value=call)
ast.copy_location(newnode, node)
ast.fix_missing_locations(newnode)
return newnode
# Return the original node if we don't want to change it.
return node
def visit_Compare(self, self.explanation_param(self.pop_format_context(expl_call))
def test_compare(self):
left = ast.Name("x", ast.Load())
comp = ast.Compare(left, [])
self.expr(comp, "no comparators")
comp = ast.Compare(left, [ast.Num(4), ast.Num(5)])
self.expr(comp, "different number of comparators and operands")
comp = ast.Compare(ast.Num("blah"), [left])
self.expr(comp, "non-numeric", exc=TypeError)
comp = ast.Compare(left, [ast.Num("blah")])
self.expr(comp, exc=TypeError)
def visit_Compare(self, self.explanation_param(self.pop_format_context(expl_call))
def visit_Compare(self, self.explanation_param(self.pop_format_context(expl_call))
def test_contains_to_const(self):
# list => tuple
self.check_optimize_func("x in [1,2]", "x in (1,2)")
# set => frozenset
const = ast.Constant(value=frozenset({1, 2}))
node = ast.Compare(left=ast.Name(id='x',
ops=[ast.In()],
comparators=[const])
self.check_optimize_func("x in {1,2}", node)
# [] is not a constant: don't optimize
self.check_dont_optimize_func("x in [1,[],2]")
self.check_dont_optimize_func("x in {1,2}")
def not_compare(self, node):
compare = node.operand
if len(compare.ops) != 1:
# FIXME: optimize: 'not a <= b <= c' to 'a > b or b > c'
return
op = compare.ops[0]
try:
op = NOT_COMPARE[op.__class__]()
except KeyError:
return
new_cmp = ast.Compare(left=compare.left, ops=[op],
comparators=compare.comparators)
copy_lineno(compare, new_cmp)
return new_cmp
def do_Compare(self, node):
'''
StubFormatter ast.Compare visitor for these ops:
'==','!=','<','<=','>','>=','is','is not','in','not in',
'''
s = 'bool' # Correct regardless of arguments.
ops = ','.join([self.op_name(z) for z in node.ops])
self.trace_visitor(node, ops, s)
return s
# If(expr test,stmt* orelse)
def get_condition_rhs_num(if_node):
assert isinstance(if_node, ast.If)
assert isinstance(if_node.test, ast.Compare)
assert isinstance(if_node.test.comparators[0], ast.Num)
return if_node.test.comparators[0].n
def get_condition_lhs(if_node):
assert isinstance(if_node, ast.Compare)
return unparse(if_node.test.left).strip()
def whereeval(str_, get=None):
"""Evaluate a set operation string,where each Name is fetched"""
if get is None:
import redbiom
config = redbiom.get_config()
get = redbiom._requests.make_get(config)
# Load is subject to indirection to simplify testing
globals()['Load'] = make_Load(get)
formed = ast.parse(str_, mode='eval')
node_types = (ast.Compare, ast.In, ast.notin, ast.BoolOp, ast.And,
ast.Name, ast.Or, ast.Eq, ast.Lt, ast.LtE, ast.Gt, ast.GtE,
ast.NotEq, ast.Str, ast.Num, ast.Load, ast.Expression,
ast.Tuple, ast.Is, ast.IsNot)
for node in ast.walk(formed):
if not isinstance(node, node_types):
raise TypeError("Unsupported node type: %s" % ast.dump(node))
result = eval(ast.dump(formed))
# clean up
global Load
del Load
return result
def __init__(self, operators=None, functions=None, names=None):
"""
Create the evaluator instance. Set up valid operators (+,-,etc)
functions (add,random,get_val,whatever) and names. """
if not operators:
operators = DEFAULT_OPERATORS
if not functions:
functions = DEFAULT_FUNCTIONS
if not names:
names = DEFAULT_NAMES
self.operators = operators
self.functions = functions
self.names = names
self.nodes = {
ast.Num: self._eval_num,
ast.Str: self._eval_str,
ast.Name: self._eval_name,
ast.UnaryOp: self._eval_unaryop,
ast.Binop: self._eval_binop,
ast.BoolOp: self._eval_boolop,
ast.Compare: self._eval_compare,
ast.IfExp: self._eval_ifexp,
ast.Call: self._eval_call,
ast.keyword: self._eval_keyword,
ast.Subscript: self._eval_subscript,
ast.Attribute: self._eval_attribute,
ast.Index: self._eval_index,
ast.Slice: self._eval_slice,
}
# py3k stuff:
if hasattr(ast, 'NameConstant'):
self.nodes[ast.NameConstant] = self._eval_nameconstant
elif isinstance(self.names, dict) and "None" not in self.names:
self.names["None"] = None
def visit_Compare(self, node):
if len(node.ops) not in (1, 2,):
raise SyntaxError("ast.Compare with more than 2 ops: %s is not supported" % node)
(_, left), (_, ops), comps) = ast.iter_fields(node)
self.visit(left)
left = self.data.pop()
comparators = list()
for comparator in comps:
self.visit(comparator)
comparators.append(self.data.pop())
if len(ops) == 1:
right = comparators[0]
cls = criteria_class.lookup(ast_op_to_criteria.lookup(type(ops[0])))
criteria = cls(left, *right) if type(right) in (list, tuple,) else cls(left, right)
self.data.append(criteria)
else:
lower = left
lower_op = ast_op_to_operator.lookup(type(ops[0]))
one = comparators[0]
upper_op = ast_op_to_operator.lookup(type(ops[1]))
upper = comparators[1]
criteria = criteria_class.instance(Const.Between, lower, one, upper, lower_op, upper_op)
self.data.append(criteria)
def normalize(node):
if isinstance(node, ast.Compare):
return normalize_compare(node)
for key in dir(node):
if key.startswith("_"):
continue
value = getattr(node, key)
if isinstance(value, ast.AST):
setattr(node, key, normalize(value))
elif isinstance(value, list):
setattr(node, [normalize(n) for n in value])
return node
def test_compare(self):
left = ast.Name("x", exc=TypeError)
def visit_Compare(self, left_expl = self.visit(comp.left)
res_variables = [self.variable() for i in range(len(comp.ops))]
load_names = [ast.Name(v, next_expl = self.visit(next_operand)
results.append(next_res)
sym = binop_map[op.__class__]
syms.append(ast.Str(sym))
expl = "%s %s %s" % (left_expl, self.explanation_param(self.pop_format_context(expl_call))
def pythonast(self, args, tonative=False):
return ast.Compare(args[0], [ast.Eq()], [args[1]])
def pythonast(self, [ast.NotEq()], [ast.Lt()], [ast.LtE()], [ast.Gt()], tonative=False):
arg, = args
justlog = ast.Call(ast.Attribute(ast.Name("$math", "log", [arg], None, None)
if self.base == math.e:
if tonative:
return justlog
else:
return ast.IfExp(ast.Compare(arg, [ast.Num(0)]), justlog, ast.Num(-inf))
else:
scaled = ast.Binop(justlog, ast.Div(), ast.Num(math.log(self.base)))
if tonative:
return scaled
else:
return ast.IfExp(ast.Compare(arg, scaled, ast.Num(-inf))
def pythonast(self, = args
return ast.IfExp(ast.Compare(arg, [ast.Num(1)]), ast.Num(inf), ast.IfExp(ast.Compare(arg, [ast.Num(-1)]), ast.Num(-inf), ast.Call(ast.Attribute(ast.Name("$math", "atanh", None)))
def peval_single_compare(state, left, right):
func = COMPARE_OPS[type(op)]
state, result = peval_call(state, func, args=[left, right])
if not is_kNown_value(result):
state = state.update(temp_bindings=state.temp_bindings.del_(result.func.id))
result = ast.Compare(left=result.args[0], comparators=[result.args[1]])
return state, result
def translate_pat_Name_constructor(self, scrutinee_trans):
lbl = pat.id
condition = ast.Compare(
left=scrutinee_trans,
comparators=[ast.Str(s=lbl)])
return condition, _util.odict()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。