Live data from Hacker News

Common Python Mistakes

toptal.com

131–140 of 146 posts

Re: Common Python Mistakes

#131

Earlier quoted context omitted.

x isn't a variable, it's a tag. Because Python is dynamically typed, x can be an int one minute and a function the next, so every attribute on a class is stored as a pointer to an object, including attributes that are integers (which is an object) and functions (which are also objects). Because you aren't declaring the type of x (Python doesn't allow that), Python has to treat x = 1 the same way it'd treat def x(self…

Where x is an identifier (presumably aka tag?) that refers to a variable, it is not beyond the bounds of possibility for "x = 1" to be interpreted as "store the value of 1 into the variable that is referred to by identifier x". Plenty of languages, including dynamically typed ones, manage to do this, as indeed Python does in many cases. Not knowing the type of x is unrelated to question of where x's value is stored,…

I'm not really sure I understand your point. The value of x is still going to be in memory, but you may not have any references to it and it will be garbage collected. The disconnect is in thinking x is a variable and not an identifier. x points to the object in the parent until it is overridden. This allows me to dynamically alter the functionality of a class and all it's subclasses that don't override that functionality during runtime.

Re: Common Python Mistakes

#132

Earlier quoted context omitted.

Where x is an identifier (presumably aka tag?) that refers to a variable, it is not beyond the bounds of possibility for "x = 1" to be interpreted as "store the value of 1 into the variable that is referred to by identifier x". Plenty of languages, including dynamically typed ones, manage to do this, as indeed Python does in many cases. Not knowing the type of x is unrelated to question of where x's value is stored,…

I'm not really sure I understand your point. The value of x is still going to be in memory, but you may not have any references to it and it will be garbage collected. The disconnect is in thinking x is a variable and not an identifier. x points to the object in the parent until it is overridden. This allows me to dynamically alter the functionality of a class and all it's subclasses that don't override that function…

I'm not disputing how or why it works, just saying that I think it is poor design, as it causes a statement that looks like variable assignment to actually produce overriding. I think this violates the principle of least astonishment, and I suspect there is no good reason (beyond implementation simplicity) why Python class variables do behave this way.

(edit: replaced "an expression" with "a statement")

Re: Common Python Mistakes

#133

OT but this page hard crashes Safari on iPhone.

Also crashes Safari on my OS 10.5 Mac, and is unusably laggy in Firefox on the same computer. All sorts of thrashy javascript nonsense seems to be going on.

I use JavaScript Blocker for Safari, which is sort of like a less paranoid (and more convenient) version of NoScript. Looks like this site attempts to load 45 JavaScript files over 12 iframes, 17 of which JS Blocker blocked.

Mildly excessive? /s

Re: Common Python Mistakes

#134
post #70
post #39

This is a pretty good list of gotchas, but it's important when writing something targeted at beginners to be as precise and clear as possible. Nearly every section here either uses terminology poorly, is slightly incorrect, or has difficult examples. Python supports optional function arguments and allows default values to be specified for any optional argument. No, specifying a default is what causes an argument to b…

Just to notice: this text is not targeted at beginners, in my opinion. These are upper-intermediate to advanced level gotchas.

1, 2, 4, 5, and 8 all seem to me like mistakes only / primarily made by beginners. I can't see an article aimed at primarily intermediate Python users spending time on them.

3 is a really easy mistake to make for anyone (which is why the syntax was changed).

6, 7, 9 and 10 are more obscure, and where I really appreciate this article -- and they definitely can be issues for more experienced Python devs.

Re: Common Python Mistakes

#135

Earlier quoted context omitted.

I'm not really sure I understand your point. The value of x is still going to be in memory, but you may not have any references to it and it will be garbage collected. The disconnect is in thinking x is a variable and not an identifier. x points to the object in the parent until it is overridden. This allows me to dynamically alter the functionality of a class and all it's subclasses that don't override that function…

I'm not disputing how or why it works, just saying that I think it is poor design, as it causes a statement that looks like variable assignment to actually produce overriding. I think this violates the principle of least astonishment, and I suspect there is no good reason (beyond implementation simplicity) why Python class variables do behave this way. (edit: replaced "an expression" with "a statement")

No, the reason it exists is so you can override functionality of subclasses at run time, otherwise things like monkey patching would be impossible. I guess it COULD do a pass to see if the attr is an immutable or some form of primative type when __new__ is called and force those to be instantiated as instance attributes at the cost of internal consistency, but it seems pretty straight forward to me the way it works now. You don't need to be an expert, you just need a basic understand of how Python evaluates code and the difference between tags and variables.

Re: Common Python Mistakes

#136
post #49

Slightly off topic, but does anyone know of a resource that has 'most common mistakes' for different languages all in one place? It's certainly possible to google for blog posts and stack overflow questions to assemble such a list, but it would be handy to have them all in one place. My use case is when interviewing candidates I often ask them to rate themselves on a scale of 1-5 in the languages they know, and then…

I have thought about this, but in the context of understanding the root causes of these problems: 1) is it a language design problem, 2) a misunderstanding or misconception on the part of the programmer, 3) due to or related to bad coding/smells (e.g. method body too long), 4) high complexity code (could be related to (3), could reflect the domain), 5) reduced programmer cognitive capacity (distraction, stress, sleep deficit, lack of motivation, etc.).

These would be interesting research areas for instrumenting IDEs / other eco-system tools to collect some of this data. (I'm sure there is already some work in some of these areas and would appreciate names or links to high-quality reviews.)

Re: Common Python Mistakes

#137
post #85

In "Common Mistake #2", I'd say that the mistake is fairly obvious to anyone who understands even a little bit about OOP and inheritance. Since class C doesn't define its own variable x, it has to be that it inherits the x in class A, so there's no reason to be surprised that C.x changes when A.x does.

While I agree that the "problem" case can be seen as obvious when considered in isolation, really it's the behaviour of the two cases taken together that can seem inconsistent. Nothing about understanding OOP or inheritance will prepare a person for that.

This modified version of #2 might help clear things up. I've only added print statements. In general, when issues like this come up, printing the id()s of identifiers can help:

Edit: Added some extra blank lines because lines were getting joined together.

# class_variables.py

class A(object):

    x = 1
class B(A):

    pass
class C(A):

    pass
print "Initially, A.x, B.x, C.x and their ids:"

print A.x, B.x, C.x

print id(A.x), id(B.x), id(C.x)

B.x = 2

print "After B.x = 2, A.x, B.x, C.x and their ids:"

print A.x, B.x, C.x

print id(A.x), id(B.x), id(C.x)

A.x = 3

print "After A.x = 3, A.x, B.x, C.x and their ids:"

print A.x, B.x, C.x

print id(A.x), id(B.x), id(C.x)

And the output:

>python class_variables.py

Initially: A.x, B.x, C.x and their ids:

1 1 1

30519808 30519808 30519808

After B.x = 2: A.x, B.x, C.x and their ids:

1 2 1

30519808 30519796 30519808

After A.x = 3: A.x, B.x, C.x and their ids:

3 2 3

30519784 30519796 30519784

Re: Common Python Mistakes

#139
post #72

Earlier quoted context omitted.

Still hugely useful when you want to write long string constants. Imho, adding a comma after each list element is a good practice. You can easily swap them, add more, and never run into a an issue you describe: foo = [ "a", "bc", "def", # comma here, too ]

You could easily use a + operator then. I find the behavior surprising. I would expect a syntax error. You get a syntax error if you write two integers next to each other (separated by a space) or two of any other thing but somehow "a" "b" got converted to "ab". If I've discovered it myself I would be tempted to fill a bug report. It goes against Python mantra: "Explicit is better than implicit" It seems someone thou…

Yeah, when I discovered this little "feature" I had a read through that. The folks that use this for blocks of multi-line text are very defensive about the practice. I do understand not wanting to break compatibility though, especially since finding instances of this is hard (which is another reason it shouldn't exist in the first place!). Oh well :)

Re: Common Python Mistakes

#140
Any reason why you're using a slice here? >>> numbers[:] = [n for n in numbers if not odd(n)] I'm thinking that doing >>> numbers = [n for n in numbers if not odd(n)] wouldn't be a problem since the assignment is executed after the computation of the list comprehension.
Post reply on HN