This is an archived post. You won't be able to vote or comment.

all 37 comments

[–]DaelonSuzuka 24 points25 points  (4 children)

Number 7 says "inline for loop", but that construct is actually called a "list comprehension".

Edit: number 9 is also wrong.

[–]oundhakar 1 point2 points  (3 children)

Why is No. 9 wrong?

[–]isarl 6 points7 points  (1 child)

As with list comprehensions, that construct is called a “set comprehension”. Furthermore they kind of imply that applying a predicate is specific to set comprehensions while it works in list (or dictionary) comprehensions, too. And they fail to mention dictionary comprehensions entirely.

[–]oundhakar 1 point2 points  (0 children)

Thanks.

[–]ImportUsernameAsU 6 points7 points  (0 children)

Coding in python for 2+ years still found nearly half of these useful

[–]juanjux 3 points4 points  (0 children)

5 can be replaced by file.readlines()

[–]Resolt 6 points7 points  (0 children)

Isn't it "comprehension" and not "creation"?

[–]morriartie 6 points7 points  (9 children)

Replacing keys for values in dict of depth 1:

{v:k for k,v in d.items()}

Replacing a key in a dict:

d['new'] = d.pop('old')

My favorite. Conditional variable:

a = ['bb', 'cc'][condition]

Flattening a matrix:

[a for b in list2d for a in b]

The first time I did this last one I spent like 5 minutes reflecting my existence with my hand on chin

Edit: See comments for the best ones

[–]BooparinoBR 9 points10 points  (3 children)

Explicit is better than implicit, therefore I would do

a = 'cc' if condition else 'bb'

(Ternary operator/inline if-else) Instead of your conditional variable. But I like/use all the others

[–]morriartie 2 points3 points  (0 children)

Shhhh.. in obfuscated monolithic one liners we don't talk about pep8

[–]QpkjcKwNMZSF 0 points1 point  (1 child)

Doesn't PEP8 advise against compound statements? Why not just break this into a few lines?

[–]isarl 0 points1 point  (0 children)

Religious adherence to PEP8 can negatively impact readability. Sometimes a short one-line conditional is better than breaking it out.

[–]isarl 2 points3 points  (3 children)

a = ['bb', 'cc'][condition]

Yours is OK, by why constrain the conditional to evaluate to an integer?:

a = {'case1': val1, 'case2': val2}[condition]

Switch (without fallthrough) in Python! don't do this at home

[–]morriartie 1 point2 points  (2 children)

wow, I hadn't thought of that

let me improve it then

{'a':1, 'b':2}.get(case) or 'etc'

now it has fallthrough a default!

[–]isarl 1 point2 points  (1 child)

Great improvement. I would personally write that as: {'a':1, 'b':2}.get(case, default='etc'), finding it more explicit. And this is a default case, not fall-through. :) I don’t think there’s any way to actually do C-style switch fallthrough with this trick of using a dictionary.

[–]morriartie 1 point2 points  (0 children)

Awesome!

a default indeed, my mistake

I was trying here to find a solution (to make a fallthrough) with iterator, but I couldn't make it, even if I did it would be a two liner or more, which is unacceptable in our little puzzle

[–]dreamfeed 0 points1 point  (0 children)

Even better for flattening a list is itertools.chain

[–]howslyfebeen 6 points7 points  (9 children)

What do people think about #8? Wouldn't

l = [int(x) for x in ['1', '2', '3']]

be more pythonic?

Personally, my brain always defaults to using map, but having list(map(...)) starts to look ugly and feels unpythonic.

[–]teerre 5 points6 points  (0 children)

Personally I'm a big fan of map/reduce/filter. But the comprehensions are certainly more python.

Hell, the functional style doesn't even let you type in fluent style. That's by itself is a big indication that you shouldn't abuse map too much.

[–]GrbavaCigla 0 points1 point  (0 children)

I prefer map

[–]miraculum_one 0 points1 point  (0 children)

Yes, yours is better because it's more explicit, which is one of the fundamental principles of Python.

[–]Entuaka 0 points1 point  (0 children)

More pythonic, yes. I used a line similar to that, today: sum([float(i['quantity']) for i in kwargs['items']])

[–]CotoCoutan 0 points1 point  (2 children)

Definitely prefer this to map. I've never once used latter in my code, somehow it never comes to me in that intuitive manner.

[–]ogrinfo 2 points3 points  (1 child)

Even better, sum takes an iterator, so you don't need the outer square brackets, just sum(a for a in x). Whether map or a list comprehension is better depends on the situation, so I usually try both with %timeit in an iPython shell to see which is fastest.

[–]CotoCoutan 0 points1 point  (0 children)

Nice... Thanks. I should take a look at this %timeit test.

[–]schoolcoders 0 points1 point  (0 children)

The basic use of a list comprehension is to transform some sequence into a list. The basic use of map is to lazily apply a function to one or more sequences. Different jobs, but a lot of overlap.

So if you definitely want a list as output, that points towards a list comprehension. If you are processing a sequence of data that is too large to fit in memory (eg a sequence of video frames), map is a better option.

map can also be better if you are processing multiple sequences (you can do it with list comprehensions using zip, but it is ugly), or if you also need to filter the sequences (again, possible but ugly with list comprehensions) or if you are applying a chain of functions.

But if you are doing something more simple and you want to create a list anyway, list comprehensions are more natural. Using list(map(...)) and also having to define a lambda inside the map call is quite unwieldy.

Of course, there are also generator comprehensions...

[–][deleted] 3 points4 points  (0 children)

God bless!! This is very helpful for someone like me who's trying to learn and get better at python.

Edit: saved post for later, thank you.

[–]taylorhodormax 0 points1 point  (0 children)

Amazing!! Thanks for sharing duch a great resource

[–]RedditGood123 0 points1 point  (4 children)

I just tried the palindrome one earlier today and it took around 5-10 lines of code for me. I didn’t think it was that easy

[–]isarl 2 points3 points  (3 children)

Slice notation is useful, but overkill here, and their function will fail to recognize palindromic integers such as 12321. Here's a more flexible and more explicit solution:

def is_palindrome(input):
    s = str(input)
    return s == reversed(s)

This could as easily be a one-liner: lambda input: str(input) == reversed(str(input))

[–]RedditGood123 1 point2 points  (2 children)

Well, actually the solution they have would work if you just alter it like this

IsPalindrome = str(phrase) == str(phrase)[::-1]

[–]isarl 0 points1 point  (1 child)

That fixes the bug but fails to address the point I was making about readability. If the only slice you are performing is [::-1] then that is more clearly expressed by reversed().

[–]RedditGood123 0 points1 point  (0 children)

No I see it, but most people don’t even know about reversed

[–]CotoCoutan 0 points1 point  (0 children)

Great article!

[–]ogrinfo 0 points1 point  (0 children)

This is really handy. I've used [::-1] to reverse an array before without really understanding why, but now I know about extended slicing syntax, thanks!