📌  相关文章
📜  Python中的陷阱

📅  最后修改于: 2022-05-13 01:54:19.159000             🧑  作者: Mango

Python中的陷阱

对于大多数编程世界的新手来说, Python是一种首选语言。这是因为它相当简单,需求量很大,并且最终功能强大。但是有些情况可能会混淆或欺骗新手编码员。这些被称为“陷阱”!源自非正式术语“Got You!”,陷阱是程序玩诡计并导致输出与预期完全不同的情况或场景。应该注意的是,陷阱不是错误或异常。这是一个完全有效的代码,只是因为我们在编写程序时错过了一个很小的事实或要点而导致输出不正确。因此,我们也可以将陷阱视为“编码时常犯的错误”。

蟒蛇陷阱

让我们看一下 Python3 中一些最常见的问题以及如何解决它们:

  1. 括号陷阱:
  2. 当括号使用不正确或不必要时,会出现一些问题。

    例子:

    Python3
    # results in False
    print(5>2 == True)


    Python3
    # results in True
    print((5>2) == True)


    Python3
    # results in False
    print(5 is (not None))


    Python3
    # results in True
    print(5 is not None)


    Python3
    # results in True
    print(1 == True)
      
    # results in False
    print(1 is True)


    Python3
    # results in True
    print(1 != False) 
      
    # results in True
    print(1 is not False)


    Python3
    def appendNew(appendTo =[]):      
        appendTo.append(1)   
        return appendTo
          
    # Driver's code
    print(appendNew())
    print(appendNew())


    Python3
    def appendNew(appendTo = None):  
        if appendTo == None:
            appendTo =[]    
        appendTo.append(1)   
        return appendTo
          
    # Driver's code
    print(appendNew())
    print(appendNew())


    Python3
    list1 = [1, 2, 3]
    def baz1():
      
        # the code works fine
        list1.append(4) 
        return list1
    def baz2():
      
        # Doesn't work fine
        list1 += [5]      
        return list1
          
    # Driver's code
    print(baz1())
    print(baz2())


    Python3
    def create_multipliers():
      
        # lambda function creates an iterable
        # list anonymously
        return [lambda c : i * c for i in range(6)] 
      
      
    for multiplier in create_multipliers():
        print multiplier(3)


    Python3
    def create_multipliers():
        return [lambda x, i = i : i * x for i in range(6)]
          
          
    for multiplier in create_multipliers():
        print(multiplier(3))


    Python3
    # buggy program to print a list 
    # of odd numbers from 1 to 10
      
      
    even = lambda x : bool(x % 2)
    numbers = [n for n in range(10)]
      
    for i in range(len(numbers)):
        if not even(numbers[i]):
            del numbers[i]


    Python3
    # working program to print a 
    # list of odd numbers from 1 to 10
      
      
    even = lambda x : bool(x % 2)
    numbers = [n for n in range(10)]
      
    numbers[:] = [n for n in numbers if even(n)]
    print(numbers)


    输出:

    False

    这导致 False,因为上面的表达式实际上意味着 5>2 和 2==True。这意味着,真假。因此,最终结果为 False。
    它可以通过使用括号来纠正。

    Python3

    # results in True
    print((5>2) == True)
    

    输出:

    True
    

    这里还有一个例子:

    Python3

    # results in False
    print(5 is (not None)) 
    

    输出:

    False

    这是因为"is not""is""not"分开使用不同。部分(not None)等于 True,5 为 True 结果为 False。它可以通过不使用任何括号来纠正。

    Python3

    # results in True
    print(5 is not None)
    

    输出:

    True
    

  3. “is”、“==”、“is not”、“!=”:这是一个简短但非常常见的问题。许多新程序员经常认为is==是一回事。但绝对不是!

    Python3

    # results in True
    print(1 == True)
      
    # results in False
    print(1 is True) 
    

    输出:

    True
    False
    

    另一方面, is not!=是相同的。

    Python3

    # results in True
    print(1 != False) 
      
    # results in True
    print(1 is not False)
    

    输出:

    True
    True
    

  4. 默认参数 gotcha:

    在Python中,默认参数仅在函数第一次运行时声明一次,从那时起,每次都使用声明的参数。

    Python3

    def appendNew(appendTo =[]):      
        appendTo.append(1)   
        return appendTo
          
    # Driver's code
    print(appendNew())
    print(appendNew())
    

    预计每次我们调用appendNew()时,都会创建一个包含 1 的新列表。但是会发生什么:

    [1]
    [1, 1]
    

    当函数第二次运行时,不会再次创建变量appendTo 。相反,它只是第一次创建并一次又一次地使用。我们可以通过以下方式解决它:

    Python3

    def appendNew(appendTo = None):  
        if appendTo == None:
            appendTo =[]    
        appendTo.append(1)   
        return appendTo
          
    # Driver's code
    print(appendNew())
    print(appendNew())
    

    输出:

    [1]
    [1]
    

  5. 范围陷阱:

    有时,我们必须牢记我们正在处理的变量的范围,即它是全局范围(在函数内部和外部函数)还是局部范围(仅在函数内部函数)。

    例子:

    Python3

    list1 = [1, 2, 3]
    def baz1():
      
        # the code works fine
        list1.append(4) 
        return list1
    def baz2():
      
        # Doesn't work fine
        list1 += [5]      
        return list1
          
    # Driver's code
    print(baz1())
    print(baz2())
    

    输出:

    [1, 2, 3, 4]
    
    Traceback (most recent call last):
      File "/home/ba0dfa25407638b061076b45ce165ce5.py", line 15, in 
        print(baz2())
      File "/home/ba0dfa25407638b061076b45ce165ce5.py", line 10, in baz2
        list1 += [5]      
    UnboundLocalError: local variable 'list1' referenced before assignment
    

    发生这种情况是因为

    list1 += [5]

    意味着我们正在分配给变量list1但 list1 是在我们的函数范围之外定义的。在baz1()中,我们附加到 list1 而不是分配,因此它工作正常。

  6. 变量在闭包的后期绑定:

    Python有一个臭名昭著的后期绑定行为。我们的意思是,被迭代的变量的值最终确定为它到达最后一次迭代时的值。让我们看一个例子:

    Python3

    def create_multipliers():
      
        # lambda function creates an iterable
        # list anonymously
        return [lambda c : i * c for i in range(6)] 
      
      
    for multiplier in create_multipliers():
        print multiplier(3)
    

    预期的结果当然是:

    0
    3
    6
    9
    12
    15
    

    但我们得到的是:

    15
    15
    15
    15
    15
    15
    

    这是因为当循环迭代完成时, i的值为 5,因此每次 3*5 的结果为 15。
    可以通过以下方式解决:

    Python3

    def create_multipliers():
        return [lambda x, i = i : i * x for i in range(6)]
          
          
    for multiplier in create_multipliers():
        print(multiplier(3))
    

    输出:

    0
    3
    6
    9
    12
    15
    

  7. 在迭代列表时对其进行变异:

    这是新编码人员几乎一直面临的最常见问题。在使用列表或其他可变项时,如果我们在迭代它时对其进行变异,肯定会导致错误。建议我们创建列表的副本并对其进行变异而不是原始列表。

    Python3

    # buggy program to print a list 
    # of odd numbers from 1 to 10
      
      
    even = lambda x : bool(x % 2)
    numbers = [n for n in range(10)]
      
    for i in range(len(numbers)):
        if not even(numbers[i]):
            del numbers[i]
    

    输出:

    Traceback (most recent call last):
      File "/home/92eed8bfd8c92fca3cf85f22e8cfd9ea.py", line 9, in 
        if not even(numbers[i]):
    IndexError: list index out of range
    

    但是如果我们使用numbers的副本来代替:

    Python3

    # working program to print a 
    # list of odd numbers from 1 to 10
      
      
    even = lambda x : bool(x % 2)
    numbers = [n for n in range(10)]
      
    numbers[:] = [n for n in numbers if even(n)]
    print(numbers)  
    

    输出:

    [1, 3, 5, 7, 9]