The purpose of my question is to strengthen my knowledge base with Python and get a better picture of it, which includes knowing its faults and surprises. To keep things specific, I'm only interested in the CPython interpreter.

I'm looking for something similar to what learned from my PHP landmines
question where some of the answers were well known to me but a couple were borderline horrifying.

@S. Lott - Nothing wrong with it, just that I didn't know about it and no one's asked this question in SO.
–
DavidFeb 10 '09 at 4:29

1

@hop The top rated answer right now for this question isn't mentioned in the ferg.org page. Maybe if Guido had written the ferg.org page and I had known about it, then I wouldn't have bothered, but no one singular person knows everything.
–
DavidFeb 10 '09 at 18:40

Surprised? You won't be if you remember that class variables are internally handled as dictionaries of a class object. If a variable name is not found in the dictionary of current class, the parent classes are searched for it. So, the following code again, but with explanations:

This works as one might expect, except for raising a TypeError after updating the first entry of the tuple! So a will be ([42, 43, 44],) after executing the += statement, but there will be an exception anyway. If you try this on the other hand

Or you could simply write: a[0].extend([43, 44]).
–
DzinXApr 7 '11 at 9:17

1

Wow. I consider changing and raising an exception afterwards a bug in Python. Any reason why this might be just a wart?
–
AlfeSep 5 '12 at 12:24

WOW. I expected the error, but I didn't expect it to actually modify the list too. That's ugly. However, I don't believe I've ever run into this because I make a habit of not using tuples with data that I want to change. Even if it points to the same list, I'd rather the values remain immutable. If I want to have positional elements that can change, I'd either use a list, dictionary or class.
–
johannestaasFeb 7 '14 at 21:58

Definitely a gotcha. It's gotten so than adding "from future import division" to every new .py file I create is practically a reflex.
–
Chris UpchurchFeb 10 '09 at 19:18

1

Makes sense supposing that 5 and 2 are actually variables. Otherwise you could just write 5./2
–
AlgoriasFeb 10 '09 at 21:46

Why are you multiplying by 1.0? Wouldn't it be just as easy to make 5 be 5.0 or float(5) in case 5 is hidden in a variable.
–
NopeJul 27 '09 at 17:31

18

"The correct work-around is subtle: casting an argument to float() is wrong if it could be a complex number; adding 0.0 to an argument doesn't preserve the sign of the argument if it was minus zero. The only solution without either downside is multiplying an argument (typically the first) by 1.0. This leaves the value and sign unchanged for float and complex, and turns int and long into a float with the corresponding value." (PEP 238 - python.org/dev/peps/pep-0238)
–
Tom DunhamJul 28 '09 at 16:15

The only gotcha/surprise I've dealt with is with CPython's GIL. If for whatever reason you expect python threads in CPython to run concurrently... well they're not and this is pretty well documented by the Python crowd and even Guido himself.

James’ specific example was the HTTP libraries: httplib, urllib, urllib2, urlparse, mimetools, and ftplib. Some of the functionality is duplicated, and some of the functionality you'd expect is completely absent, e.g. redirect handling. Frankly, it's horrible.

If I ever have to grab something via HTTP these days, I use the urlgrabber module forked from the Yum project.

If you use global x inside of f(), that will allow you to reference variables outside of f's scope.
–
DavidFeb 21 '11 at 18:46

@David: I know why you get an error. The point of the post is that most people don't expect to get an error here, so it's a gotcha.
–
Sven MarnachFeb 21 '11 at 21:20

I was commenting more for the sake of others, not all but most of the gotchas here have solutions. For myself, I didn't even know about the global symbol/operator until two years after I started using Python.
–
DavidFeb 22 '11 at 6:25

Using global variables such as that is a bad code smell, anyways. I'm glad you didn't come across it till 2 years in. Means you're not getting functions to perform on global scope variables.
–
Zoran PavlovicDec 18 '12 at 8:40

@ZoranPavlovic: You get the same issue when using closures instead of global variables. A counter implemented as a closure would be perfectly reasonable, but you have to be careful.
–
Sven MarnachDec 18 '12 at 20:29

This actually burnt me in an answer here on SO, since I had tested it outside a function and got the change I wanted. Afterwards, I found it mentioned and contrasted to the case of globals() in "Dive Into Python." See example 8.12. (Though it does not note that the change via locals() will work at the top level as I show above.)

Isn't rather the result of print what comes as a surprise, than what happens in the comparison? x + y would also lead to something rather unexpected here as all kinds of operations between x and y.
–
jolviMar 19 at 15:16