Commit a53a17ea authored by Stefan Behnel's avatar Stefan Behnel

optimise iteration over dict(something).items()

parent 58897392
......@@ -159,14 +159,25 @@ class IterationTransform(Visitor.VisitorTransform):
if function.is_attribute and not reversed and not arg_count:
base_obj = iterator.self or function.obj
method = function.attribute
# in Py3, items() is equivalent to Py2's iteritems()
is_safe_iter = self.module_scope.context.language_level >= 3
if not is_safe_iter and method in ('keys', 'values', 'items'):
# try to reduce this to the corresponding .iter*() methods
if isinstance(base_obj, ExprNodes.SimpleCallNode):
inner_function = base_obj.function
if (inner_function.is_name and inner_function.name == 'dict'
and inner_function.entry
and inner_function.entry.is_builtin):
# e.g. dict(something).items() => safe to use .iter*()
is_safe_iter = True
is_py3 = self.module_scope.context.language_level >= 3
keys = values = False
if method == 'iterkeys' or (is_py3 and method == 'keys'):
if method == 'iterkeys' or (is_safe_iter and method == 'keys'):
keys = True
elif method == 'itervalues' or (is_py3 and method == 'values'):
elif method == 'itervalues' or (is_safe_iter and method == 'values'):
values = True
elif method == 'iteritems' or (is_py3 and method == 'items'):
elif method == 'iteritems' or (is_safe_iter and method == 'items'):
keys = values = True
if keys or values:
......
......@@ -470,3 +470,15 @@ def optimistic_iterdict_change_size(d):
if count > 5:
break # safety
return "DONE"
@cython.test_assert_path_exists(
"//WhileStatNode",
"//WhileStatNode//DictIterationNextNode")
def values_of_expression(**kwargs):
"""
>>> sorted(values_of_expression(a=3, b=4))
[3, 4]
"""
# this can be optimised even in Py2
return [ arg for arg in dict(kwargs.items()).values() ]
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment