Python 2.x gotchas and landmines

后端 未结 23 2195
北恋
北恋 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:21

    One of the biggest surprises I ever had with Python is this one:

    a = ([42],)
    a[0] += [43, 44]
    

    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

    a = ([42],)
    b = a[0]
    b += [43, 44]
    

    you won't get an error.

    0 讨论(0)
  • 2020-11-28 18:21
    def f():
        x += 1
    
    x = 42
    f()
    

    results in an UnboundLocalError, because local names are detected statically. A different example would be

    def f():
        print x
        x = 43
    
    x = 42
    f()
    
    0 讨论(0)
  • 2020-11-28 18:21

    If you create a list of list this way:

    arr = [[2]] * 5 
    print arr 
    [[2], [2], [2], [2], [2]]
    

    Then this creates an array with all elements pointing to the same object ! This might create a real confusion. Consider this:

    arr[0][0] = 5
    

    then if you print arr

    print arr
    [[5], [5], [5], [5], [5]]
    

    The proper way of initializing the array is for example with a list comprehension:

    arr = [[2] for _ in range(5)]
    
    arr[0][0] = 5
    
    print arr
    
    [[5], [2], [2], [2], [2]]
    
    0 讨论(0)
  • 2020-11-28 18:22

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

    Not including an __init__.py in your packages. That one still gets me sometimes.

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

    Due to 'truthiness' this makes sense:

    >>>bool(1)
    True
    

    but you might not expect it to go the other way:

    >>>float(True)
    1.0
    

    This can be a gotcha if you're converting strings to numeric and your data has True/False values.

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