Alternative to Dict Comprehension Prior to Python 2.7

Alternative to dict comprehension prior to Python 2.7

Use:

gw_func_dict = dict((chr(2**i), func) for i, func in enumerate(gwfuncs[:8]))

That's the dict() function with a generator expression producing (key, value) pairs.

Or, to put it generically, a dict comprehension of the form:

{key_expr: value_expr for targets in iterable <additional loops or if expressions>}

can always be made compatible with Python < 2.7 by using:

dict((key_expr, value_expr) for targets in iterable <additional loops or if expressions>)

Down-converting dictionary comprehensions to generator expressions for Python 2.6 compliance

You can always write a source-processor that converts your 2.7 code to 2.6 code.

Or, just use one that someone else wrote. The 3to2 project has, among its fixers, one named dctsetcomp.* And it looks like it does exactly what you want. Here's a sample of its output:

RefactoringTool: Refactored dc.py
--- dc.py (original)
+++ dc.py (refactored)
@@ -1 +1 @@
-{x(i):y(i) for i in z}
+dict((x(i), y(i)) for i in z)
RefactoringTool: Files that need to be modified:
RefactoringTool: dc.py

There's not much documentation on how to use it, but basically it's meant to work exactly like 2to3, which is documented nicely, and used in hundreds of projects on PyPI if you need examples.

You can manually run this on your code before you're ready to distribute it, or run it as a pre-build step in setup.py (either unconditionally, or only if running on 2.6). setuptools makes it trivial to add a 2to3 step to the build/install process; subverting that to run 3to2 instead should be easy, but I haven't actually tried it.


You might want to look at the source to 3to2, or the stdlib's 2to3, if you want to write your own fixers, or if you need to debug/improve this one, or want to write a simpler parser from scratch.


A third place you can run a fixer is at runtime, with an import hook. Look at MacroPy as a great example of an import hook.

MacroPy is also a great example of code that works on ASTs instead of raw source. If you wanted to build a distribution-time fixer, this might be handy, because then you could let Python 2.7 parse the Python 2.7 source so you don't have to.


If 3to2 doesn't work out, you can probably do something a lot simpler, by limiting what you write in your code to what your parser can handle. For example, you could set yourself the rule that a dict comprehension must be the only dict display on the line, and be followed by #dc. Then you just have to search for lines ending with #dc, find the braces, and parse the result—which means you only have to parse a small subset of Python that's a regular language, which means you can do it with simple regexps.


* Why would a tool designed to port 3.2+ code to 2.7 have a dict comprehension fixer? Because it was originally designed to port 3.1+ code to 2.6, and the author never removed the no-longer-needed fixers. So, you got lucky. :)

Can I avoid such cumbersome list comprehension

A dictionary can be initialized with an iterable, returning iterables with exactly two objects. This should do it:

d = dict([item.split('=', 1) for item in a])

Alternatively, you could use map():

d = dict(map(lambda item: item.split("=", 1), a))

Python Dictionary comprehension for a list of dictionaries

in_list = [{'fips': '01001', 'state': 'AL', 'name': 'Autauga County'}, 
{'fips': '20005', 'state': 'KS', 'name': 'Atchison County'},
{'fips': '47145', 'state': 'TN', 'name': 'Roane County'}]

out_dict = {x['name']: 'United States' for x in in_list if 'name' in x}

Some notes for learning:

  • Comprehensions are only for Python 2.7 onwards
  • Dictionary comprehensions are very similar to list comprehensions except with curly braces {} (and keys)
  • In case you didn't know, you can also add more complicated control-flow after the for loop in a comprehension such as [x for x in some_list if (cond)]

For completeness, if you can't use comprehensions, try this

out_dict = {}

for dict_item in in_list:
if not isinstance(dict_item, dict):
continue

if 'name' in dict_item:
in_name = dict_item['name']
out_dict[in_name] = 'United States'

As mentioned in the comments, for Python 2.6 you can replace the {k: v for k,v in iterator} with:

dict((k,v) for k,v in iterator)

You can read more about this in this question

Happy Coding!

How to convert Python dictionary syntax from 2.7 to 2.6?

So, in both versions this is totally over-engineered.

rpmDict = {rpmList[i]: rpmList_full[i] for i in range (len(rpmList))}

Should just be:

rpmDict = dict(zip(rpmList, rpmList_full))

And:

rpmDataDict = {rpmDataTextList[i]: rpmDataTextList_full[i] for i in range (len(rpmDataTextList))}

Should just be:

rpmDataDict = dict(zip(rpmDataTextList, rpmDataTextList_full))

But as the other answer has noted, in Python2.6,

{expression0: expression1 for whatever in some_iterable}

Can be converted into

dict((expression0, expression1) for whatever in some_iterable)

Note also, you really should be using Python 3 as much as possible. In any case, in Python 2, use:

from future_builtins import zip

So that zip creates an iterator, not a list, which is more efficient, especially for larger data.

python dict comprehension working locally but not on server - version issue

2.6 does not have dict comprehension change it to

itemsKeyedById = dict((i["id"], i) for i in myList)

afaik it also does not have set comprehension nor set literals(unrelated to your question but another datastructure in 2.7 that is not in 2.6) ... you actually need to do set([1,2,3])

syntax error when trying to use for loop inside dict.update

Dict comprehensions were added in Python2.7 and 3.0. They do not exist in Python2.6.

Python 2.6 compatibility for rundeckrun

As Kevin points out, this is a dictionary comprehension.

In Python 2.6, you can write it as a generator expression yielding a list of tuples (key/value pairs) and pass that to the dict constructor:

data = dict((k, getattr(self, k))
for k in node_attr_keys if getattr(self, k, None) is not None)

Are there dictionary comprehensions in Python? (Problem with function returning dict)

edit: As agf pointed out in comments and the other answer, there is a dictionary comprehension for Python 2.7 or newer.

def countChar(word):
return dict((item, word.count(item)) for item in set(word))

>>> countChar('google')
{'e': 1, 'g': 2, 'o': 2, 'l': 1}
>>> countChar('apple')
{'a': 1, 'p': 2, 'e': 1, 'l': 1}

There is no need to convert word to a list or sort it before turning it into a set since strings are iterable:

>>> set('google')
set(['e', 'o', 'g', 'l'])

There is no dictionary comprehension with for Python 2.6 and below, which could be why you are seeing the syntax error. The alternative is to create a list of key-value tuples using a comprehension or generator and passing that into the dict() built-in.



Related Topics



Leave a reply



Submit