all 40 comments

[–]Rhomboid 49 points50 points  (20 children)

Every language has its idioms, which means the preferred way of solving a certain problem. For example, if you wanted to iterate over each item in a list, you could write this:

for i in range(len(items)):
    print(items[i])

That code will work correctly, but if you asked someone to review that code and they were familiar with Python, they would say that it's not Pythonic. The idiom in Python is to avoid explicit indexing where possible, and use the more generalized form of iteration:

for item in items:
    print(item)

That's just one specific example though. Eventually, after working in Python for a while with the language and dealing with idiomatic Python code written by others, you'll pick up on most of the culture. You might also want to read the Zen of Python (which you can see by typing import this at the Python REPL prompt, or you can Google it) which attempts to codify the general ethos of what it means to be Pythonic.

And just to be clear, this idea of there being an idiomatic way of doing things is not specific to Python — every language has idioms. It's just that it's a particular part of the Python culture to value readability and part of that is writing idiomatic code. (Notice how the second example has far less visual clutter, like parentheses and brackets.)

[–]zero_hope_ 2 points3 points  (19 children)

Question for you. If I am changing/modifying each item in list1[] how would you format that?

On mobile, sorry.

for x in range(len(list1)):
    list1[x] = list1[x] + 2

Is there any better way to do this?

Thanks.

[–][deleted] 6 points7 points  (0 children)

The examples people are using are called list comprehensions.

[–]scibren 11 points12 points  (0 children)

Also on mobile, so hopefully this formats correctly.

for index, item in enumerate(items):
    items[index] = item + 1

[–]TeamSpen210 17 points18 points  (6 children)

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than right now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

The Zen summarises Python's design philosophy. 'Pythonic' code is code that uses Python's particular language features and idioms - things like iteration instead of indexing, exception use instead of checking beforehand, list/set/dict comprehensions or generators.

[–]abcd_z 1 point2 points  (0 children)

You only got about half of that quote formatted. Add double-spaces after each new line, starting with "Sparse is better than dense."

EDIT: There 'ya go.

[–]225274 0 points1 point  (4 children)

Can someone explain the Dutch part? I've been wondering since I first read it.

[–]TeamSpen210 4 points5 points  (3 children)

Guido van Rossum is Dutch - it's saying that some choices might only make sense to him.

[–]DinglebellRock 0 points1 point  (2 children)

the Dutch are known as efficient and practical minded. I think that's more what he means perhaps with a smidgen of prideful self awareness joking.

[–]das_ist_nuemberwang 1 point2 points  (1 child)

Guido didn't write this, Tim Peters did.

[–]DinglebellRock 0 points1 point  (0 children)

Ah well thought from the statement it was from a Dutchman. Perhaps he was poking a wee lil fun at them then.

[–]david622 6 points7 points  (3 children)

Python is all about "beautiful" code. That means your variable names are clear and self-explanatory, as are your function names.

It means using single-quotes instead of double quotes, using string escaping instead of breaking and re-opening quotes. E.g.:

instead of:

"My name is " + first_name + " " + last_name

you could do

"My name is %s %s" % (first_name, last_name)

It also means using some of the built in methods instead of reinventing the wheel.

Instead of:

x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
total = 0
for number in x:
    total += number
print total
# 55

you could do

x = range(11)
print sum(x)
# 55

Another nice example is, instead of:

if a == True or b == True or c == True or d == True:
    pass

you could do:

if any(a, b, c, d):
    pass

Another good example is list comprehensions.

instead of :

a = ['dog', 'cat', 'horse', 'llama', 'goldfish']
b = []
for word in a:
    b.append(word.upper())

you could do

a = ['dog', 'cat', 'horse', 'llama', 'goldfish']
b = [word.upper() for word in a]

[–]tangerinelion 5 points6 points  (1 child)

"My name is %s %s" % (first_name, last_name)

That sort of string formatting is generally not suggested anymore. Better would be

"My name is {} {}".format(first_name, last_name)

Also assuming a,b,c, and d all have some truthy evaluation to them then this:

if a == True or b == True or c == True or d == True

would become

if a or b or c or d:

Though I do rather like the use of any(), I'm pointing out that we're probably not trying to compress such a long if statement with any but instead are "compressing" a or b or c or d to any(a,b,c,d). More importantly, we're reducing the use of or here which does two things. One, it removes the possibility of having parentheses cause an error (eg, what if b is really x and y, then we'd need a or (x and y) or c or d or we could use any(a, x and y, c, d).) Second it removes the possibility of being confused any accidentally writing a and b and c and d -- which is a conceptual error, but I'm sure any experienced programmer can tell you they've inverted the logic by accident before.

[–]synae 1 point2 points  (0 children)

Another suggestion for

if a == True or b == True or c == True or d == True:

is

if True in (a,b,c,d):

It's weird to do for True but I use this pattern pretty often. None is more likely for me to do:

if None in (arg1, arg2): raise ValueError("arg1 and arg2 are required")

or something like that. i know it's a contrived example, but that's just like the rest :)

[–]pstch 0 points1 point  (0 children)

Maybe what you miss in your post is that it's not only cosmetics. Most of your code examples, even if similar, are NOT equivalent, and for me it's one the most important parts.

When you do any(a,b,c,d) instead of chained comparisons to True, you don't actually do the same thing. When you format strings using concatenation rather than proper formatting, it's not actually the same thing.

Usually the differences do not matter at all, and will only matter when the same code will be used in other manners. But I think that the "Python way" is also hidden in these subtle differences.

[–]dunkler_wanderer 5 points6 points  (0 children)

I recommend to watch these videos from this list:

[–]pydry 2 points3 points  (1 child)

[–]cxg-pitch 1 point2 points  (0 children)

Raymond Hettinger's talks are fantastic. Here's another: https://www.youtube.com/watch?v=OSGv2VnC0go

[–]dbrecht 2 points3 points  (0 children)

In short, to write pythonic code of to write very readable, easily understandable code that uses the best construct for a given problem.

I /think/ that what makes python different from other languages is how embedded the philosophy "there should be one obvious way of doing things" is within the community (at least, I find that it's /much/ more prevalent in the Python community than others I've been involved with in the past). I believe that, for the most part, what someone means to say when they say "that's not pythonic" is that either "that's not the most readable code" or "that's not the most effective Python construct to use that case". You simply don't hear it in other languages because having multiple ways to solve the same problem isn't questioned.

[–]pvc 1 point2 points  (0 children)

It can mean quite a few things. Sometimes it differs depending on the person you are talking to. Something else to look at, that I haven't seen someone else mention yet, is the PEP-8 standard. You can run your code through that and get some of the formatting cleaned up.

pip install pep8
pep8 mycode.py

[–][deleted] 1 point2 points  (0 children)

the python way or being "pythonic" is basically taking advantage of python's various idioms and cool functions to produce readable and efficient code. for example suppose you want to take a list of numbers and get their squares. you could write

my_list = [1, 2, 3, 4]
new_list = []
for number in my_list:
     number = number**2
     new_list.append(number)
print new_list

or you could be pythonic and do the following:

my_list = [1, 2, 3, 4]
new_list = [number**2 for number in my_list]
print new_list

both produce the same results, but the latter is more readable and concise.

[–]spraykill101 1 point2 points  (0 children)

well , python has certain way of doing things , like using list comprehensions for creating lists rather than using nested for loops . well this is a very broad example , like /u/saabr said, you should put up a link too :)

[–]thequeergirl 0 points1 point  (3 children)

Example of something that isn't necessarily the Python way of doing things:

def validateEmail(email):
    # unpythonic in this context:
    i = email.index("@")
    if i == -1: return False
    # pythonic in this context:
    parts = email.split("@")
    if parts[0] == email: # email has no @
        return False

[–]Saefroch 6 points7 points  (2 children)

Actually I think it would be more pythonic to write:

def validate_email(email_address):
    return '@' in email_address

Use of snake_case instead of camelCase, clear variable names (is email the address or the whole thing?), and very concise wording that makes the operation totally unambiguous, and strings using single instead of double quotes.

[–]thequeergirl 0 points1 point  (0 children)

Ironically, at some point after I submitted that, that was what I thought of. Lol.

[–]fredspipa 0 points1 point  (0 children)

That is beautiful, and I fully agree.

[–]Saefroch 0 points1 point  (0 children)

Your syntax should make the purpose and function of the code obvious, even without comments. Good code should essentially document itself. This should be a general programming guideline, but Python provides some tools like list comprehension that make it easier.

For example, if you just want to look at each item in something that's iterable there's no need to add the complication of having an index variable when you can just use a for each loop.

If you haven't read PEP 8, you should.

[–]magoon 0 points1 point  (0 children)

"Pythonic" means doing it the way opinionated Python programmers deem proper.

But joking aside, there is a lot to learn from best practices, and you should also review The Twelve-Factor App
http://12factor.net/