Live data from Hacker News

Anti-Patterns in Python Programming

lignos.org

91–100 of 242 posts

Re: Anti-Patterns in Python Programming

#91

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).

Even clearer:

    x = [for word in words: for letter in word: letter]
This also has the advantage of being readable left to right without encountering any unbound identifiers like all other constructs in Python.

Re: Anti-Patterns in Python Programming

#92
post #66

Earlier quoted context omitted.

I'm not sure what you're getting at here, or what you are expecting tuples to be like. They can have as much "structure" as you need--they're just a collection. Lighter-weight, immutable collections have a use case. The code in OP appears to be one where it makes sense. I follow the rule where variables are mutable IFF they need to be mutable.

Tuples by pythonists are used as they were mere lists, just immutable. This is clearly displayed by Python's own interface. For the rest of the world, tuples are not immutable lists. They are tuples, i.e. collections of "objects" that could share nothing about their type. Tuples often are not even iterable! (Erlang, Haskell) The fact that tuples in Python can have as much structure as one wants is derived from dynami…

I'm sorry, I don't see clearly what a tuple should be. What would be different about Python tuples if they were true tuples?

Re: Anti-Patterns in Python Programming

#93

Earlier quoted context omitted.

The l (lowercase L) and the 1 (one) look really similar. Could that be the cause of some confusion? Of course, the function name helps, but most developers have learned not to trust function names to be an accurate description of what the function does, especially in tricky interview questions. Still, I'd change this to something like: def append_five(l=[]): l.append(5) return l It tests the same thing (knowledge of…

Not the op, but I'd accept the confusion response of: [[]] [[],[]] [[],[],[]] because the behavior is the same, whether or not they misread an 'l' as a 1.

Python doesn't seem to agree with you :^)

  In [1]: a = []

  In [2]: a.append(a)

  In [3]: a
  Out[3]: [[...]]

  In [4]: a[0]
  Out[4]: [[...]]

  In [5]: a[0][0]
  Out[5]: [[...]]

  In [6]: a[0][0][0]
  Out[6]: [[...]]

  In [7]: a[0][0][0][0]
  Out[7]: [[...]]

  In [8]: a.append(a)

  In [9]: a
  Out[9]: [[...], [...]]

  In [10]: a[0][1][0] is a
  Out[10]: True

  In [11]: id(a)
  Out[11]: 4547140064

  In [12]: id(a[0][1][0])
  Out[12]: 4547140064

Re: Anti-Patterns in Python Programming

#94
post #72
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…

> 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]: class B(object0:
       ...:
    KeyboardInterrupt

    In [6]: class B(object):
       ...:     l = None
       ...:     def __init__(self):
       ...:         self.l = []
       ...:

    In [7]: c, d = B(), B()

    In [8]: c.l.append("Something")

    In [9]: c.l, d.l
    Out[9]: (['Something'], [])

Re: Anti-Patterns in Python Programming

#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.

Re: Anti-Patterns in Python Programming

#96
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 main logic live in the outer scope because I often inspect variables "after the fact" in iPython.

How should I be doing this?

Re: Anti-Patterns in Python Programming

#97
> PEP 8 is the universal style guide for Python code.

> If you aren't following it, you should have good reasons beyond "I just don't like the way that looks."

Core dev and Guido have said many times PEP 8 are not holy.

See https://mail.python.org/pipermail/python-dev/2010-November/1...

In essence, a "stupid reason" like "I don't like it" is a valid reason not to adopt PEP 8.

In fact, I don't like the PEP 8 recommendation on docstring. I like Google's docstring (aka napoleon in Sphinx contrib-module).

http://sphinxcontrib-napoleon.readthedocs.org/en/latest/exam...

Re: Anti-Patterns in Python Programming

#98
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.

Re: Anti-Patterns in Python Programming

#99
post #52
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!

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.

In case you're using Python 3, why not write ssl_args: dict, ssl: bool=False?

Re: Anti-Patterns in Python Programming

#100
post #34
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!

Couldn't agree more! One of my all time new python interview questions gets a surprisingly large number of developers. Given a function like: def append_one(l=[]): l.append(1) return l What does this return each time? >>> append_one() >>> append_one() >>> append_one()

Wow, that is really ugly semantics. Here are some notes of mine on how hard R works to avoid exposing this sort of aliasing/mutability issue to the user: http://www.win-vector.com/blog/2014/04/you-dont-need-to-unde...
Post reply on HN