Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 2.x gotchas and landmines [closed]

Tags:

python

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.

Update: Apparently one maybe two people are upset that I asked a question that's already partially answered outside of Stack Overflow. As some sort of compromise here's the URL http://www.ferg.org/projects/python_gotchas.html

Note that one or two answers here already are original from what was written on the site referenced above.

like image 288
David Avatar asked Feb 09 '09 23:02

David


2 Answers

Expressions in default arguments are calculated when the function is defined, not when it’s called.

Example: consider defaulting an argument to the current time:

>>>import time >>> def report(when=time.time()): ...     print when ... >>> report() 1210294387.19 >>> time.sleep(5) >>> report() 1210294387.19 

The when argument doesn't change. It is evaluated when you define the function. It won't change until the application is re-started.

Strategy: you won't trip over this if you default arguments to None and then do something useful when you see it:

>>> def report(when=None): ...     if when is None: ...         when = time.time() ...     print when ... >>> report() 1210294762.29 >>> time.sleep(5) >>> report() 1210294772.23 

Exercise: to make sure you've understood: why is this happening?

>>> def spam(eggs=[]): ...     eggs.append("spam") ...     return eggs ... >>> spam() ['spam'] >>> spam() ['spam', 'spam'] >>> spam() ['spam', 'spam', 'spam'] >>> spam() ['spam', 'spam', 'spam', 'spam'] 
like image 83
Garth Kidd Avatar answered Sep 20 '22 15:09

Garth Kidd


You should be aware of how class variables are handled in Python. Consider the following class hierarchy:

class AAA(object):     x = 1  class BBB(AAA):     pass  class CCC(AAA):     pass 

Now, check the output of the following code:

>>> print AAA.x, BBB.x, CCC.x 1 1 1 >>> BBB.x = 2 >>> print AAA.x, BBB.x, CCC.x 1 2 1 >>> AAA.x = 3 >>> print AAA.x, BBB.x, CCC.x 3 2 3 

Surprised? You won't be if you remember that class variables are internally handled as dictionaries of a class object. For read operations, 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:

# AAA: {'x': 1}, BBB: {}, CCC: {} >>> print AAA.x, BBB.x, CCC.x 1 1 1 >>> BBB.x = 2 # AAA: {'x': 1}, BBB: {'x': 2}, CCC: {} >>> print AAA.x, BBB.x, CCC.x 1 2 1 >>> AAA.x = 3 # AAA: {'x': 3}, BBB: {'x': 2}, CCC: {} >>> print AAA.x, BBB.x, CCC.x 3 2 3 

Same goes for handling class variables in class instances (treat this example as a continuation of the one above):

>>> a = AAA() # a: {}, AAA: {'x': 3} >>> print a.x, AAA.x 3 3 >>> a.x = 4 # a: {'x': 4}, AAA: {'x': 3} >>> print a.x, AAA.x 4 3 
like image 28
DzinX Avatar answered Sep 19 '22 15:09

DzinX