Python中的陷阱
对于大多数编程世界的新手来说, Python是一种首选语言。这是因为它相当简单,需求量很大,并且最终功能强大。但是有些情况可能会混淆或欺骗新手编码员。这些被称为“陷阱”!源自非正式术语“Got You!”,陷阱是程序玩诡计并导致输出与预期完全不同的情况或场景。应该注意的是,陷阱不是错误或异常。这是一个完全有效的代码,只是因为我们在编写程序时错过了一个很小的事实或要点而导致输出不正确。因此,我们也可以将陷阱视为“编码时常犯的错误”。
让我们看一下 Python3 中一些最常见的问题以及如何解决它们:
- 括号陷阱:
- “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
- 默认参数 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]
- 范围陷阱:
有时,我们必须牢记我们正在处理的变量的范围,即它是全局范围(在函数内部和外部函数)还是局部范围(仅在函数内部函数)。
例子:
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 而不是分配,因此它工作正常。 - 变量在闭包的后期绑定:
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
- 在迭代列表时对其进行变异:
这是新编码人员几乎一直面临的最常见问题。在使用列表或其他可变项时,如果我们在迭代它时对其进行变异,肯定会导致错误。建议我们创建列表的副本并对其进行变异而不是原始列表。
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]
当括号使用不正确或不必要时,会出现一些问题。
例子:
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