Python 2.x gotchas and landmines

后端 未结 23 2192
北恋
北恋 2020-11-28 17:47

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 sp

相关标签:
23条回答
  • 2020-11-28 18:05

    x += [...] is not the same as x = x + [...] when x is a list`

    >>> x = y = [1,2,3]
    >>> x = x + [4]
    >>> x == y
    False
    
    >>> x = y = [1,2,3]
    >>> x += [4]
    >>> x == y
    True
    

    One creates a new list while the other modifies in place

    0 讨论(0)
  • 2020-11-28 18:06

    List slicing has caused me a lot of grief. I actually consider the following behavior a bug.

    Define a list x

    >>> x = [10, 20, 30, 40, 50]
    

    Access index 2:

    >>> x[2]
    30
    

    As you expect.

    Slice the list from index 2 and to the end of the list:

    >>> x[2:]
    [30, 40, 50]
    

    As you expect.

    Access index 7:

    >>> x[7]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    IndexError: list index out of range
    

    Again, as you expect.

    However, try to slice the list from index 7 until the end of the list:

    >>> x[7:]
    []
    

    ???

    The remedy is to put a lot of tests when using list slicing. I wish I'd just get an error instead. Much easier to debug.

    0 讨论(0)
  • 2020-11-28 18:10

    You cannot use locals()['x'] = whatever to change local variable values as you might expect.

    This works:
    
    >>> x = 1
    >>> x
    1
    >>> locals()['x'] = 2
    >>> x
    2
    
    BUT:
    
    >>> def test():
    ...     x = 1
    ...     print x
    ...     locals()['x'] = 2
    ...     print x  # *** prints 1, not 2 ***
    ...
    >>> test()
    1
    1
    

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

    0 讨论(0)
  • 2020-11-28 18:11

    There was a lot of discussion on hidden language features a while back: hidden-features-of-python. Where some pitfalls were mentioned (and some of the good stuff too).

    Also you might want to check out Python Warts.

    But for me, integer division's a gotcha:

    >>> 5/2
    2
    

    You probably wanted:

    >>> 5*1.0/2
    2.5
    

    If you really want this (C-like) behaviour, you should write:

    >>> 5//2
    2
    

    As that will work with floats too (and it will work when you eventually go to Python 3):

    >>> 5*1.0//2
    2.0
    

    GvR explains how integer division came to work how it does on the history of Python.

    0 讨论(0)
  • 2020-11-28 18:15

    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
    
    0 讨论(0)
  • 2020-11-28 18:16

    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.

    A long but thorough explanation of CPython threading and some of the things going on under the hood and why true concurrency with CPython isn't possible. http://jessenoller.com/2009/02/01/python-threads-and-the-global-interpreter-lock/

    0 讨论(0)
提交回复
热议问题