Live data from Hacker News

Anti-Patterns in Python Programming

lignos.org

101–110 of 242 posts

Re: Anti-Patterns in Python Programming

#101
post #95

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 happ…

Especially taking into account the more bizarre bugs (features?) of python: (bool(datetime.time(0)), bool(datetime.time(1))) == (False, True) I always consider `if x:` a bug, unless x can only be a boolean. Furthermore, it seriously hinders readability and clarity of the code.

Agreed. Especially if you program in more than one language, trying to remember the subtleties of each one's collection of rules for "truthiness" is a fraught exercise. And isn't it Python people who like to say, "explicit is better than implicit"?

Re: Anti-Patterns in Python Programming

#102
post #3

The more frequent and dangerous pitfalls are, in my humble opinion: - Bare except: statements (that catches everything , even Ctrl-C) - Mutables as default function/method arguments - Wildcard imports!

I agree that bare excepts are bad, however they do not catch Ctrl-C. If you _do_ want to catch Ctrl-C you have to except a KeyboardInterrupt explicitly.

This is untrue (just tested) for at least Python 2.7.x. under Linux, try ... except catches Ctrl-C.

Re: Anti-Patterns in Python Programming

#103
post #94
post #72

Earlier quoted context omitted.

> 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 va…

It has something to do with mutability, because if an object is immutable, the behavior of Python matches what the naive developer expects. It's only mutable objects that break those expectations. Don't even get into unexpected behavior in classes: In [1]: class A(object): ...: l = [] ...: In [2]: a, b = A(), A() In [3]: a.l.append("Something") In [4]: a.l Out[4]: ['Something'] In [5]: b.l Out[5]: ['Something'] In [6…

The other scoping issue in python that always struck me as strange is that loop variables aren't scoped to the loop, they continue to exist after the loop completes. I can see the logic for this feature even if I don't agree with it, but what I really don't get is that the loop variables are not defined if you iterate over something that is empty:

   >>> for item in [1]:
   ...   print item
   1
   >>> item
   1

   >>> for i in []:
   ...   print i
   
   >>> i
   Traceback (most recent call last):
     File "", line 1, in 
   NameError: name 'i' is not defined
I would expect i == None. That oddity makes it dangerous to use the feature unless you're really careful (e.g. using a for - else construct).

Re: Anti-Patterns in Python Programming

#104
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 think only the second is truly bug-free. The first only does what the user expects if they pass in a non-empty list:

  my_list = []
  append_one(my_list)
  # my_list didn't get anything appended to it
This shows up another subtle trap related to the "truthiness" (or falsiness in this case) of things like the empty list.

Re: Anti-Patterns in Python Programming

#105

The only thing I disagree with is "use nested comprehensions" thing. In my mind: x = [letter for word in words for letter in word] is inside-out or backwards or backwards. I want the nested for being the less specific case: x = [letter for letter in word for word in words] makes more sense in my mind. (It's also my first answer to the "what're some warts in the your language of choice).

I'm in the camp that if your list comp needs more than one for clause, it's complicated enough to be broken out into actual for loop.

Re: Anti-Patterns in Python Programming

#106
I don't think there us such thing as a pattern per language, unless the language is really unique. IMO what does exists is Language Bad Practices, which are actually tied to the language itself.

An (anti)pattern is something abstract and can be applied to any other similar language.

Re: Anti-Patterns in Python Programming

#107

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?

Admittedly, my thought would be to chain the calls, not nest them: alist = words.filter(lambda word: word.startswith('a') .map(foo) That being said, my Python is limited and I don't know it filter/map are available as methods of a list. At the end of the day, there are cases where list comprehensions are much cleaner/understandable... and cases where the reverse is true.

> I don't know it filter/map are available as methods of a list.

They're not. Which is a shame in my opinion, because as you've written it you can clearly read the operations in the order they happen, ie. filter followed by map. Instead, you do have to do the second line of what blossoms wrote above.

And I don't think it's possible to write a list comprehension that reads in execution order, either :(

Re: Anti-Patterns in Python Programming

#108
post #94
post #72

Earlier quoted context omitted.

> 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 va…

It has something to do with mutability, because if an object is immutable, the behavior of Python matches what the naive developer expects. It's only mutable objects that break those expectations. Don't even get into unexpected behavior in classes: In [1]: class A(object): ...: l = [] ...: In [2]: a, b = A(), A() In [3]: a.l.append("Something") In [4]: a.l Out[4]: ['Something'] In [5]: b.l Out[5]: ['Something'] In [6…

I'm sorry, but I don't understand why you would think this as unexpected behaviour? For the class A, the list l is a class-level attribute, hence it can be referred via either a or b objects, but for class B, after initialisation, l is an object attribute, so it is different for both c and d.

Re: Anti-Patterns in Python Programming

#109

I use python for datamining, and most of my work is done exploring data in iPython. > First, don't set any values in the outer scope that > aren't IN_ALL_CAPS. Things like parsing arguments are > best delegated to a function named main, so that any > internal variables in that function do not live in the > outer scope. How do I inspect variables in my main function after I get unexpected results? I always have my mai…

If you are using the interpreter directly then that particular bit of advice is hard to follow since you basically live in global all the time. For that reason I would say that this advice applies mainly to .py files.

Re: Anti-Patterns in Python Programming

#110
post #32

Earlier quoted context omitted.

Of, off the top of my head: for word in (set(lyrics_list) & set(words)): print('{} is in the lyrics'.format(word))

Even shorter, nice. How about this one liner, the last bit is looking a bit messy any ideas? print " is in the lyrics \n".join([set(lyrics_list) & set(words)]), "is in the lyrics"

How about

  >>> lyrics_list = ["her", "name", "is", "rio"]
  >>> words = ["is", "rio"]
  >>> print '\n'.join("{} is in the lyrics".format(word) for word in set(lyrics_list) & set(words))
  rio is in the lyrics
  is is in the lyrics
Post reply on HN