Original: Dan Bader – danbader.org


When I learn a new trick for my “Python coding toolbox” I often sense some benefit right away.

It’s like I KNOW this thing is useful for something—

And yet I’m sitting here banging my head against the table trying to find a practical application for it.

How do you take a new function or module you heard about, and turn it into a sprinkling of Pythonic fairy dust that gets you a “ooh, nice!” comment in your next code review?

The other day I got this question from newsletter reader Paul, in response to a piece I wrote about Python’s “enumerate()” function:

<br />Yesterday I needed to write a dictionary that reversed the enumeration (so, <code>{'Bob': 0}</code>, etc). I used the length of the list plus zip in a dictionary comprehension.

Is there a more Pythonic way to do this?

To give you some more context, this is what Paul wants to do:

input = ['Duration', 'F0', 'F1', 'F2', 'F3']
output = {'Duration': 0, 'F0': 1, 'F1': 2, 'F2': 3, 'F3': 4}

And this is how he accomplished it:

>>> {f:i for f, i in zip(input, range(len(input)))}
{'Duration': 0, 'F0': 1, 'F1': 2, 'F2': 3, 'F3': 4}

So far so good—but as Paul suspects, we can clean this up some more.

This is exactly the kind of situation I find myself in all the time. Paul KNOWS there’s a way to make his code more Pythonic with the enumerate() function…

But how should he put it in practice?

My first thought was that we could shorten this code a bit by avoiding the dict comprehension:

>>> dict(zip(features, range(len(input))))
{'Duration': 0, 'F0': 1, 'F1': 2, 'F2': 3, 'F3': 4}

That’s slightly cleaner (because it has less visual noise), but just like Paul I’m still not very fond of the “range(len(…))” construct.

Let’s try playing with enumerate():

>>> list(enumerate(input))
[(0, 'Duration'), (1, 'F0'), (2, 'F1'), (3, 'F2'), (4, 'F3')]

Okay, so I can use enumerate to pair each input key with its index in the list. Let’s turn that into a dictionary:

>>> dict(enumerate(input))
{0: 'Duration', 1: 'F0', 2: 'F1', 3: 'F2', 4: 'F3'}

We’re so close! This is basically what we want, but “in the wrong direction.”

Instead of mapping keys to indices it’s mapping the index to the key.

How can we reverse it?

Let’s bring back the dict comprehension:

>>> {f: i for i, f in enumerate(features)}
{'Duration': 0, 'F0': 1, 'F1': 2, 'F2': 3, 'F3': 4}

And there you go, that’s it! It’s a beauty!

Now, what’s the takeaway from all of this?

With this sort of thing, it often pays off to go with your gut.

You see, Paul was right all along. There really was a way this code could be cleaned up by using enumerate().

It was just a little unclear of how it would work specifically.

So, when you find yourself in the same situation, keep digging!

Python is an excellent programming language to do this sort of hands-on experimentation with:

When I sat down to reply to Paul’s email, the first thing I did was to fire up a Python interpreter session for some explorative code golf.

You can’t really do this with a compiled language like C++. And it’s one of Python’s great features that you should use to your advantage.

That “ooh, nice!” code review comment is waiting for you. 

Happy Pythoning!

— Dan Bader

Anúncios

Escrito por zrhans

Professor at UFSM

1 comentário

Deixe um comentário

Faça o login usando um destes métodos para comentar:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

w

Conectando a %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.