1. 首页
  2. Python

python中你常踩得坑,你碰到过嘛?网友:学到了学到了

“u003Cdivu003Eu003Cpu003E下面就让我来盘点盘点python中的坑吧!u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp9.pstatp.comu002Flargeu002Fdfic-imagehandleru002F5b2ddbe1-4018-4b13-9fb2-b44aced1e394″ img_width=”1024″ img_height=”685″ alt=”python中你常踩得坑,你碰到过嘛?网友:学到了学到了” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Ch1u003Eu003Cstrongu003E列表创建和引用u003Cu002Fstrongu003Eu003Cu002Fh1u003Eu003Cpu003Eu003Cstrongu003E嵌套列表的创建u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E使用*号来创建一个嵌套的list:u003Cu002Fpu003Eu003Cpreu003Eli = [[]] * 3u003Cbru003Eprint(li)u003Cbru003E# Out: [[], [], []]u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E通过这个方法,可以得到一个包含3个list的嵌套list,我们来给第一个list增加一个元素:u003Cu002Fpu003Eu003Cpreu003Eli[0].append(1)u003Cbru003Eprint(li)u003Cbru003E# Out: [[1], [1], [1]]u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E通过输出的结果可以看初,我们只给第一元素增加元素,结果三个list都增加了一个元素。这是因为[[]]*3并不是创建了三个不同list,而是创建了三个指向同一个list的对象,所以,当我们操作第一个元素时,其他两个元素内容也会发生变化的原因。效果等同于下面这段代码:u003Cu002Fpu003Eu003Cpreu003Eli = []u003Cbru003Eelement = [[]]u003Cbru003Eli = element + element + elementu003Cbru003Eprint(li)u003Cbru003E# Out: [[], [], []]u003Cbru003Eelement.append(1)u003Cbru003Eprint(li)u003Cbru003E# Out: [[1], [1], [1]]u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E我们可以打印出元素的内存地址一探究竟:u003Cu002Fpu003Eu003Cpreu003Eli = [[]] * 3u003Cbru003Eprint([id(inner_list) for inner_list in li])u003Cbru003E# Out: [6830760, 6830760, 6830760]u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E到这我们可以明白原因了。那如何解决了?可以这样:u003Cu002Fpu003Eu003Cpreu003Eli = [[] for _ in range(3)]u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E这样我们就创建了三个不同的list对象u003Cu002Fpu003Eu003Cpu003Eprint([id(inner_list) for inner_list in li])u003Cu002Fpu003Eu003Cpu003E# Out: [6331048, 6331528, 6331488]u003Cu002Fpu003Eu003Ch1u003Eu003Cstrongu003E列表元素的引用u003Cu002Fstrongu003Eu003Cu002Fh1u003Eu003Cpu003E不要使用索引方法遍历list,例如:u003Cu002Fpu003Eu003Cpreu003Eu003Cbru003Efor i in range(len(tab)):u003Cbru003E print(tab[i])u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E比较好的方法是:u003Cu002Fpu003Eu003Cpreu003Efor elem in tab:u003Cbru003Eprint(elem)u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003Efor语句会自动生成一个迭代器。如果你需要索引位置和元素,使用enumerate函数:u003Cu002Fpu003Eu003Cpreu003Efor i, elem in enumerate(tab):u003Cbru003E print((i, elem))u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E注意 == 符号的使用u003Cu002Fpu003Eu003Cpreu003Eif (var == True):u003Cbru003E # 当var是:True、1、 1.0、 1L时if条件成立u003Cbru003Eif (var != True):u003Cbru003E # 当var不是 True 和 1 时if条件成立u003Cbru003Eif (var == False):u003Cbru003E # 当var是 False 或者 0 (or 0.0, 0L, 0j) if条件成立u003Cbru003E u003Cbru003Eif (var == None):u003Cbru003E # var是None if条件成立u003Cbru003E u003Cbru003Eif var:u003Cbru003E # 当var非空(None或者大小为0)对象 stringu002Flistu002Fdictionaryu002Ftuple, non-0等if条件成立u003Cbru003E u003Cbru003Eif not var:u003Cbru003E # 当var空(None或者大小为0)对象 stringu002Flistu002Fdictionaryu002Ftuple, non-0等if条件成立u003Cbru003E u003Cbru003Eif var is True:u003Cbru003E # 只有当var时True时 if条件成立 1也不行u003Cbru003E u003Cbru003Eif var is False:u003Cbru003E # 只有当var时False时 if条件成立 0也不行u003Cbru003E u003Cbru003Eif var is None:u003Cbru003E# 和var == None 一致u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E不够优雅的代码:u003Cu002Fpu003Eu003Cpreu003Eif os.path.isfile(file_path):u003Cbru003E file = open(file_path)u003Cbru003Eelse:u003Cbru003E # do somethingu003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E比较好的做法:u003Cu002Fpu003Eu003Cpreu003Etry:u003Cbru003E file = open(file_path)u003Cbru003Eexcept OSError as e:u003Cbru003E # do somethingu003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E在python2.6+的里面可以更简洁:u003Cu002Fpu003Eu003Cpreu003Ewith open(file_path) as file:u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E之所以这么用,是这么写更加通用,比如file_path给你传个None就瞎了,还得判断是不是None,如果不判断,就又得抓异常,判断的话,代码有多写了很多。u003Cu002Fpu003Eu003Cpu003E类变量初始化u003Cu002Fpu003Eu003Cpu003E不要在对象的init函数之外初始化类属性,主要有两个问题u003Cu002Fpu003Eu003Culu003Eu003Cliu003E如果类属性更改,则初始值更改。u003Cu002Fliu003Eu003Cliu003E如果将可变对象设置为默认值,您将获得跨实例共享的相同对象。u003Cu002Fliu003Eu003Cu002Fulu003Eu003Cpu003E错误示范(除非你想要静态变量)u003Cu002Fpu003Eu003Cpreu003E“`u003Cbru003E class Car(object):u003Cbru003E color = “red”u003Cbru003E wheels = [Wheel(), Wheel(), Wheel(), Wheel()]u003Cbru003E“`u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E正确的做法:u003Cu002Fpu003Eu003Cpreu003E“`u003Cbru003E class Car(object):u003Cbru003E def __init__(self):u003Cbru003E self.color = “red”u003Cbru003E self.wheels = [Wheel(), Wheel(), Wheel(), Wheel()]u003Cbru003E“`u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E**函数默认参数**u003Cu002Fpu003Eu003Cpreu003E“`u003Cbru003Edef foo(li=[]):u003Cbru003E li.append(1)u003Cbru003E print(li)u003Cbru003E u003Cbru003Efoo([2])u003Cbru003E# Out: [2, 1]u003Cbru003Efoo([3])u003Cbru003E# Out: [3, 1]u003Cbru003E“`u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E该代码的行为与预期的一样,但如果我们不传递参数呢?u003Cu002Fpu003Eu003Cpreu003E“`u003Cbru003Efoo()u003Cbru003E# Out: [1] As expected…u003Cbru003E u003Cbru003Efoo()u003Cbru003E# Out: [1, 1] Not as expected…u003Cbru003E“`u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E这是因为函数参数类型是定义是确认的而不是运行时,所以在两次函数调用时,li指向的是同一个list对象,如果要解决这个问题,可以这样:u003Cu002Fpu003Eu003Cpreu003E“`u003Cbru003Edef foo(li=None):u003Cbru003E if not li:u003Cbru003E li = []u003Cbru003E li.append(1)u003Cbru003E print(li)u003Cbru003E u003Cbru003Efoo()u003Cbru003E# Out: [1]u003Cbru003E u003Cbru003Efoo()u003Cbru003E# Out: [1]u003Cbru003E“`u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E这虽然解决了上述的问题,但,其他的一些对象,比如零长度的字符串,输出的结果就不是我们想要的。u003Cu002Fpu003Eu003Cpreu003E“`u003Cbru003Ex = []u003Cbru003Efoo(li=x)u003Cbru003E# Out: [1]u003Cbru003E u003Cbru003Efoo(li=””)u003Cbru003E# Out: [1]u003Cbru003E u003Cbru003Efoo(li=0) u003Cbru003E# Out: [1]u003Cbru003E“`u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E最常用的办法是检查参数是不是Noneu003Cu002Fpu003Eu003Cpreu003E“`u003Cbru003Edef foo(li=None):u003Cbru003E if li is None:u003Cbru003E li = []u003Cbru003E li.append(1)u003Cbru003E print(li)u003Cbru003E u003Cbru003Efoo()u003Cbru003E# Out: [1]u003Cbru003E“`u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E**在遍历时修改**u003Cu002Fpu003Eu003Cpu003Efor语句在遍历对象是会生成一个迭代器,如果你在遍历的过程中修改对象,会产生意想不到的结果:u003Cu002Fpu003Eu003Cpreu003Ealist = [0, 1, 2]u003Cbru003Efor index, value in enumerate(alist):u003Cbru003E alist.pop(index)u003Cbru003Eprint(alist)u003Cbru003E# Out: [1]u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E第二个元素没有被删除,因为迭代按顺序遍历索引。上述循环遍历两次,结果如下:u003Cu002Fpu003Eu003Cpreu003E# Iteration #1u003Cbru003Eindex = 0u003Cbru003Ealist = [0, 1, 2]u003Cbru003Ealist.pop(0) # removes ‘0’u003Cbru003E u003Cbru003E# Iteration #2u003Cbru003Eindex = 1u003Cbru003Ealist = [1, 2]u003Cbru003Ealist.pop(1) # removes ‘2’u003Cbru003E u003Cbru003E# loop terminates, but alist is not empty:u003Cbru003Ealist = [1]u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E如果避免这个问题了,可以创建另外一个listu003Cu002Fpu003Eu003Cpreu003Ealist = [1,2,3,4,5,6,7]u003Cbru003Efor index, item in reversed(list(enumerate(alist))):u003Cbru003E # delete all even itemsu003Cbru003E if item % 2 == 0:u003Cbru003E alist.pop(index)u003Cbru003Eprint(alist)u003Cbru003E# Out: [1, 3, 5, 7]u003Cbru003Eu003Cu002Fpreu003Eu003Cu002Fdivu003E”

原文始发于:python中你常踩得坑,你碰到过嘛?网友:学到了学到了

主题测试文章,只做测试使用。发布者:逗乐男神i,转转请注明出处:http://www.cxybcw.com/12982.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code