Live data from Hacker News

Anti-Patterns in Python Programming

lignos.org

231–240 of 242 posts

Re: Anti-Patterns in Python Programming

#231
post #225
post #223

Earlier quoted context omitted.

I've seen this trotted out time and time again, and at least in this simplified form it's a red herring. If you're going to mutate the argument, it doesn't make sense to give it a default value. If you're going to return a modified form of the input you need to make a copy of it. Doing both is simply absurd.

Disagree. Would say it's a decent violation of expectations for the same instance to be passed into every invocation. Of course, the counterargument is 'know your tools,' which I'm partial to, but the fact that this pops up is an indication it is counterintuitive.

I actually agree it's counterintuitive. But this particular example makes no sense, nobody should be writing real-world code that looks like this in the first place. Either modify the original or return a copy, don't try to do both.

Re: Anti-Patterns in Python Programming

#232

Earlier quoted context omitted.

I'm talking strictly about multi "for" comprehensions. They just are too confusing to me and most of the people I've worked with ever. But we also use lots (most) python features fully, just that one has been the source of dozens of bugs in this one codebase, not to mention others I've worked on with other people. It is a shitty non-intuitive syntax. Nested for loops, flatten(), various itertools functions and chaine…

I think you are trying to justify your strange preferences after the fact. How exactly were there bugs caused by nested for loops that you encountered? It's not like if you mess up the order it will actually run without throwing an exception. Nested list comprehensions are idiomatic python. It's really strange that you don't let your team use them because you are afraid of them.

Well, Google doesn't recommend it either (http://google-styleguide.googlecode.com/svn/trunk/pyguide.ht...), but I guess they are all bloody noobs or whatever.

I mean, single level comprehension is good. Nested list comprehension is OK only in most trivial cases. In my opinion, if I see how a person uses list comprehension, I can tell, what kind of person this is.

There are people who, for example, do this def all_is_okey_dorey(lst): return all([some_predicate_fn(x) for x in lst])

instead of this def all_is_okey_dorey(lst): for x in lst: if not some_predicate_fn(x): return False return True

and can live with themselves somehow.

Or there are people, who refuse to acknowledge the existence of anything besides Python 3.x and when forced to write in 2.x use list comprehension instead of iterator comprehension.

Thing is, the validity of using nested list comprehension depends not on the amount of for loops you have, but on the thing you want to do with the item. If it's just selection, then it might be ok. If you want to apply some kind of function to it, then it's most probably the case of trying to be too clever.

Re: Anti-Patterns in Python Programming

#233
post #68

> Consider using xrange in this case. Is xrange still a thing? doesn't range use a generator instead of creating a list nowadays?

Yes, I'd revise as "Consider using Python 3 in this case." This is a chief reason why I now avoid Python 2. Python 3 is more than five years old. Where we have discretion to choose Python 3, it's time to exercise that discretion. Not because 3 is greater than 2. Because Python 2 has prominent pains that are healed in Python 3.

Re: Anti-Patterns in Python Programming

#234
post #219

Earlier quoted context omitted.

It's not broken when you understand that functions are objects and default parameters are just members of those objects. Each time the function is executed you get local vars that point to these object members. If one is a mutable type, any changes you make to it will then obviously persist.

It leaves me wondering, are the parameters also scoped to the class(seeing as they're declared at the same time)? Wouldn't this cause an issue with concurrent access to the function?

In Python there's no such thing, because GIL. Maybe in JPython.

Re: Anti-Patterns in Python Programming

#235
post #150

Earlier quoted context omitted.

Everybody, listen to this person!

Then it turns into this: x = [] for word in words: for letter in word: x.append(letter) Which in addition to being far more verbose and less readable, is also less efficient.

It's not all or nothing. One, last? for loop can be list comp.

Re: Anti-Patterns in Python Programming

#236

Earlier quoted context omitted.

For loops can often be avoided. I would write this particular example in one of these ways, that I think are readable: x = [] for word in words: x.extend(word) from itertools import chain x = [letter for letter in chain(*words)] x = list(chain(*words))

Wouldn't chain(*words) require unpacking all of words before feeding it into the chain function, storing a second copy of the word list in memory?

Yes it would, but I don't care about these small efficiencies, say 97% of the time ;)

The lazy version in Python 3 would be this one:

    list(chain(*map(iter, words)))
For Python 2 one has to use itertools.imap instead of map.

Re: Anti-Patterns in Python Programming

#237

Earlier quoted context omitted.

I think you are trying to justify your strange preferences after the fact. How exactly were there bugs caused by nested for loops that you encountered? It's not like if you mess up the order it will actually run without throwing an exception. Nested list comprehensions are idiomatic python. It's really strange that you don't let your team use them because you are afraid of them.

Well, Google doesn't recommend it either ( http://google-styleguide.googlecode.com/svn/trunk/pyguide.ht... ), but I guess they are all bloody noobs or whatever. I mean, single level comprehension is good. Nested list comprehension is OK only in most trivial cases. In my opinion, if I see how a person uses list comprehension, I can tell, what kind of person this is. There are people who, for example, do this def all_i…

The only thing wrong with that list comprehension version is those [ ]

    all(some_predicate_fn(x) for x in lst)
Much better than the loop.

Re: Anti-Patterns in Python Programming

#238
post #10

> write a list comprehension (...) code just looks a lot cleaner and what you're doing is clearer. I know how to use list comprehensions, but often avoid using them and use the standard for loops. List comprehensions look nice and clean for small examples, but they can easily get long and become mentally hard to parse. I would rather go for three 30 character lines instead of one 90 character line.

I'm a bit torn on it. In a case where you need to do a lot of nested appends, I've found that even a long list comprehension can be easier to read. You just have to be sure to properly indent it and break it up into multiple lines. My rule is that every extra `for` starts a new line, and sometimes moving the predicate to its own line when it's too long, too.

For a concrete example, I was just recently converting a list-of-dicts into a dict-of-dicts. Here's an isolated snippet:

http://pastebin.com/8q46bK0v

To my eye, the list comprehension version is reasonable. But I like the imperative style better: it uses the most basic language features and at a glance you can tell what it does. My favourite is the dictionary comprehension version, it's the shortest but still conveys clearly what it's doing.

Re: Anti-Patterns in Python Programming

#239
post #56

Earlier quoted context omitted.

The key is object mutability. A list type is mutable and a tuple type is immutable. If the candidate correctly deduces what will happen, I'll ask them to write a bug-free version, which looks like one of the below: def append_one(var=None): var = var or [] var.append(1) return var def append_one(var=None): if var is None: var = [] var.append(1) return var Mutability is a very subtle but very important concept to unde…

Since append doesn't return a value, how about: def append_one(var=None): return (var or []) + [1] Would this take longer and/or use more storage for long lists as vars?

I like this, very elegant actually.

Re: Anti-Patterns in Python Programming

#240
post #238

Earlier quoted context omitted.

I'm a bit torn on it. In a case where you need to do a lot of nested appends, I've found that even a long list comprehension can be easier to read. You just have to be sure to properly indent it and break it up into multiple lines. My rule is that every extra `for` starts a new line, and sometimes moving the predicate to its own line when it's too long, too.

For a concrete example, I was just recently converting a list-of-dicts into a dict-of-dicts. Here's an isolated snippet: http://pastebin.com/8q46bK0v To my eye, the list comprehension version is reasonable. But I like the imperative style better: it uses the most basic language features and at a glance you can tell what it does. My favourite is the dictionary comprehension version, it's the shortest but still conveys…

Yeah, I prefer the dict comprehension.

I use dict comprehensions quite frequently in my own code as well.

Post reply on HN