Live data from Hacker News

Anti-Patterns in Python Programming

lignos.org

71–80 of 242 posts

Re: Anti-Patterns in Python Programming

#71

Speaking of find\_item, is the `for..else` loop (which can be used to write find\_item in another way) considered Pythonic? I personally like `for..else` loops but I don't know where the consensus is at.

http://en.wikipedia.org/wiki/No_true_Scotsman

Don't ask what's "more Pythonic" or "less Pythonic", Python is not a cult, it's a very practical scripting language. Ask for benefits and weaknesses of a given approach in given circumstances.

Re: Anti-Patterns in Python Programming

#72
post #56

Earlier quoted context omitted.

I'm not a Python expert, but iirc from various blog posts the "l" variable does not get reset between function calls which will cause undesired behavior. So calling the function 3 times without argument would produce a list of size 1,2, and 3 with the third call rather than 3 lists of size 1. Can any Python guru's confirm?

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…

> The key is object mutability. A list type is mutable and a tuple type is immutable.

I don't think the question has much to do with mutability, it isn't surprising to me nor would I imagine most programmers that a list is mutable, that's very common.

The surprising part of this question is that the default value of 'l' continues to exist outside the lexical scope of the function, the expected behavior is that the value of 'l' is initialized at function call time and is garbage collected after each call. As it sits, using default values in python is sort of like defining a global that only has a named reference inside the function block, which is very strange.

Re: Anti-Patterns in Python Programming

#73
post #56

Earlier quoted context omitted.

I'm not a Python expert, but iirc from various blog posts the "l" variable does not get reset between function calls which will cause undesired behavior. So calling the function 3 times without argument would produce a list of size 1,2, and 3 with the third call rather than 3 lists of size 1. Can any Python guru's confirm?

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…

I'm not a Python dev, but I've been meaning to learn for a while. So this is really interesting stuff. A few questions, if you don't mind.

I understand mutability and immutability in other languages (and I gave your link a quick read to make sure there weren't any weird Python-specific rules), so I understand how the list can change and still be the same object, but a tuple or string would not. But why does that mean that the default parameter object remains in existence throughout all calls, instead of being recreated each time it is called?

Is there a reason for this being the default behavior? It seems like the majority of the time you would want to use a default parameter, you'd want it to behave like your bug-free examples.

Re: Anti-Patterns in Python Programming

#74

Earlier quoted context omitted.

alist = [foo(word) for word in words if word.startswith('a')] alist = map(foo, filter(lambda word: word.startswith('a'), words)) Which reads better?

Those are not equivalent. You need to wrap the map in a list() call.

In Python 3 you'd be right, but I think people still call mostly that language "Python 3" and mean Python 2 when they say "Python".

Re: Anti-Patterns in Python Programming

#75
post #63
post #52

Earlier quoted context omitted.

Agreed on all counts. However I do find myself using mutables as default arguments sometimes because the generated documentation is clearer. For example, this is a real method in one of my projects: def listen(self, address, ssl=False, ssl_args={}): pass I like the way this turns up in the docs because it's immediately clear that ssl_args needs to be a dict. Otherwise I have to describe it in words.

Well, that's throwing people implementing subclasses under the bus, IMO. Why not just add @param annotations in your docstrings instead?

> Well, that's throwing people implementing subclasses under the bus, IMO.

If they need to touch this argument in an overridden method and they don't know what they are doing, then yes.

> Why not just add @param annotations in your docstrings instead?

I'm using Sphinx and it renders them separately. I want the empty dict to show up in the function signature.

Re: Anti-Patterns in Python Programming

#76
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?

Well, I'd say no, not in "Python".

It seems to me that when people say "Python" they still mostly mean Python 2, where range returns a list and xrange a generator. In Python 3 there is no xrange and range returns a generator, but I think people still most often call that language "Python 3", not "Python".

Re: Anti-Patterns in Python Programming

#78
post #23

Instead of this: # Do this lyrics_set = set(lyrics_list) # Linear time set construction words = make_wordlist() for word in words: if word in lyrics_set: # Constant time print word, "is in the lyrics" You could do this: lyrics_set = set(lyrics_list) words = set(make_wordlist()) matched_words = list(lyrics_set & words) for word in matched_words: print word, "is in the lyrics"

   matched_words = set(lyrics_list).intersection(make_wordlist())

Re: Anti-Patterns in Python Programming

#80
Mmm... you should always use 'if x is not None:' imo.

It's very common for libraries to make values evaluate to False, and very easy to get bugs if you just lazily test with 'if x'.

Sqlalchemy springs to mind immediately as one of the common ones where using any() and if x: is a reeeeeallly bad idea; there are plenty of others.

I'm pretty skpetical about modifying your coding behavior based on what libraries you happen to be currently using.

'If x' isn't your friend.

Post reply on HN