> 文档中心 > Python 易错点大集合

Python 易错点大集合


文章持续更新中......

目录

一、错误地使用replace函数

【错误用法和出现的情形】

【正确做法】

二、错误地创建多维列表

【错误用法和出现的情形】

【正确做法】

三、错误地修改变量的值

【错误用法和出现的情形】

【正确做法】

四,错误地调用全局变量

【错误用法和出现的情形】

【正确做法】

五、错误地使用lambda匿名函数

【错误用法和出现的情形】

【正确做法】

六、错误地拷贝嵌套列表

【额外解决方法】

七、对函数的默认参数认知有误

【错误用法和出现的情形】

【正确做法】


一、错误地使用replace函数

错误用法和出现的情形

#当我们对一个序列进行操作时,有时会遇到要删去一个序列中的某一段,如对于下面的字符串string和列表lisstring = '123'lis = [1,2,3]#列表我们可以用remove的方法对其进行操作(或者del)lis.remove(2)#再看到字符串,del string[1] 可以吗?#显然不行,这会报错!#于是我们就想到用字符串的replace方法#然后!就有小伙伴自以为是地以为replace方法与remove方法类似,都是对原序列进行操作!string.replace('2','')#然而!执行上述语句后,lis变成了[1,2],而string还是'123'!(这里不会报错)

正确做法

string = '123'string = string.replace('2','')#此时string的结果为'13'

二、错误地创建多维列表

错误用法和出现的情形

#在创建长度较长的一维列表时,使用乘法创建是个不错的选择lis = [0,0,0,0,0,0,0,0,0,0]     #一般创建方式lis = [0]*10      #乘法创建方式#显然,这样是没有任何问题的,而且对于非常长的列表,乘法创建会使列表看起来更加优雅#但是!对于创建多维列表时,这样做是存在重大问题的!#一般人,会这样创建二维列表lis1 = [[0,0,0,0,0],[0,0,0,0,0]]#但就有的小伙伴投机取巧lis2 = [[0]*5]*2#然而!这个二维列表lis表面上是[[0,0,0,0,0],[0,0,0,0,0]],和一般创建没有区别,但其实问题巨大!lis1[1][1] = 1lis2[1][1] = 1#按道理,这两个列表的修改后的结果应该一样,但实际上'''>>>lis1>>>[[0, 0, 0, 0, 0],    [0, 1, 0, 0, 0]]>>>lis2>>>[[0, 1, 0, 0, 0],    [0, 1, 0, 0, 0]]'''#他俩长得一点儿都不一样!

正确做法

#这是由于嵌套列表用乘法创建时,内层的小列表只是引用到同一个地方而已,并不会开辟一个新的内存空间lis = [[0]*5 for _ in range(2)]

三、错误地修改变量的值

错误用法和出现的情形

#当我们要对字符串进行合并操作时,我们会这样a = '123'b = '456'a += b#运用加法赋值运算符,可以使a变成'123456'#显然,这没有任何问题!#但是!当有很多变量要进行相同的操作时,就有小伙伴自作聪明a,b,c,d = [1,2,3,4]for i in [a,b,c,d]:    i = i*4+5/3#看上去没有任何问题,其实问题大大!#此时将a,b,c,d打印出来'''>>>a,b,c,d>>>1,2,3,4'''#没有任何变化!

正确做法

#这是由于for循环只是修改了列表里的值而已,而列表只是引用了a,b,c,d的值,并不是引用这几个变量(相当于修改临时值)a,b,c,d = [1,2,3,4]lis = [a,b,c,d]for i in range(len(lis)):    lis[i] = i*4+5/3a,b,c,d = lis

四,错误地调用全局变量

错误用法和出现的情形

#当我们在函数中调用函数外部的局部变量时,容易被这几个情况弄得稀里糊涂#情形一counter = 0def access():    counter += 1    print(counter)access()#情形二counter = 0def access():    print(counter)access()#在这里,情形一会报错!(counter没有被定义)而情形二不会!

正确做法

#在局部变量不存在的情况下会自动调用全局变量,这是对的(关键在于调用)#但是,这里我们忽略了一个小细节,#“+=”是“加法赋值运算符”,在Python中属于赋值运算符中的一种#也就是说,“counter += 1”是给变量counter赋值,但它并没有调用全局变量counter(等号后的才会被调用)#要加法赋值,必须要先有变量才行,自然会报错,且报错内容是#local variable 'counter' referenced before assignment(局部变量“counter”在赋值前引用)#我们用关键字对counter变量进行声明,声明其为全局变量counter = 0def access():    global counter    counter += 1    print(counter)access()#下面是关键字global的代码解释def func1():    global value    value = 1func1()def func2():    print(value)func2()

五、错误地使用lambda匿名函数

错误用法和出现的情形

#我们有时候要多个有一定规律的函数运行后产生结果时,一般人会这样def func1(t):print((1,t))def func2(t):print((2,t))def func3(t):print((3,t))def func4(t):print((4,t))def func5(t):print((5,t))for func in [func1,func2,func3,func4,func5]:    func(1)#这样输出的结果为'''(1, 1)(2, 1)(3, 1)(4, 1)(5, 1)'''#但是!总有小伙伴投机取巧lis = [lambda t:(v0,t) for v0 in [1,2,3,4,5]]for i in lis:print(i(1))#这种错误可能在我们遇到闭包时会经常出现def func():    return [lambda t:(v0,t) for v0 in [1,2,3,4,5]]for f in func():    print(f(1))#以上两段代码的输出均为'''(5, 1)(5, 1)(5, 1)(5, 1)(5, 1)'''#v0取的值都是最后一个,然而这并不是我们预期的结果!#这在Tkinter界面化编程中也有体现,比如在使用多个重复但位置不同的Button控件

正确做法

#之前的代码中,v0保留的是最近的值#但是!如果我们将v0声明为关键字参数,问题就解决了#因为一旦函数被定义,其关键字参数的值是不变的lis = [lambda t,v0=v0:(v0,t) for v0 in [1,2,3,4,5]]for i in lis:print(i(1))

六、错误地拷贝嵌套列表

额外解决方法

#这个想必我们大家都比较熟悉了吧?#对于一维列表,我们可以用一下三种方式进行拷贝lis = [1,2,3]lis1 = lis[:]lis2 = lis.copy()#内置函数from copy import *lis3 = copy(lis)#copy模块里的函数#对于二维嵌套列表,上述的三种方法全部失效!#现在我们所知道的解决办法是from copy import copylis = [[1,2],[3,4]]lis4 = deepcopy(lis)#但是这里我想介绍一种不用引入copy模块中的deepcopy函数就可以解决的办法#注意:Python内置函数中有copy,但没有deepcopylis = [[1,2],[3,4]]lis5 = eval(str(lis))#注意:嵌套列表的拷贝与上面讲到的嵌套列表的乘法创建不同,下面的方法依然是浅拷贝lis6 = [i for i in lis]

七、对函数的默认参数认知有误

错误用法和出现的情形

#大家对函数的默认参数应该了解不少吧?#下面的做法或许我们经常会用到def function(argument,default_argument=[]):    default_argument.append(argument)    print(default_argument)function(1)#输出为[1],这看似没什么毛病,也确实没什么毛病#其实它有没有毛病就取决于你要怎么用这个函数#当我们要重复使用这个函数时,就有问题了def function(argument,default_argument=[]):    default_argument.append(argument)    print(default_argument)function(1)function(4,default_argument=[2,3])function(5)#你认为上面的输出结果是什么呢?#一般人就会认为是:'''[1][2, 3, 4][5]'''#想必你也是这样想的吧?#如果你这样想就大错特错了!!!#真实的输出是这样的:'''[1][2, 3, 4][1, 5]'''

正确做法

#其实这是我们对函数的默认参数理解错误导致的#默认参数的意思是,如果没有传递参数,那么函数就会取这个参数的默认值,这一点没有问题#但关键就在于这个默认值是什么!不会有人以为是等号后面的值吧?#如果认为是等号的值,那就错了!#等号后面的是默认参数的初始值!并不是默认值!#其实Python中的函数也是一个对象,在第一次执行函数时就会对其进行初始化,而它也是有一些属性和方法的#这个默认值就是它的属性之一,随着函数的多次使用,它在内存的值会慢慢改变#而函数每次取其默认值是从内存中取的,而不是重新将默认参数赋值为等号后面的值!def function(argument,default_argument=[]):    default_argument.append(argument)    return default_argument#将print改为returnfor i in range(10):    function(i)print(function(10))#输出结果为[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]#若我们不想要这样的结果,而是要该函数每次执行后默认参数就是空列表("[]")的话,应该这样def function(argument,default_argument=[]):    default_argument.append(argument)    return default_argument#将print改为returnfor i in range(10):    function(i,[])print(function(10,[]))#输出结果为[10]

文章持续更新中......