说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

Python开发者最常犯的10个错误

HTML文档下载 WORD文档下载 PDF文档下载
Python是一门简单易学的编程语言,语法简洁而清晰,并且拥有丰富和强大的类库。在日常开发中,开发者很容犯一些低级的错误,本文总结了开发者最容易犯的10个错误。

Python是一门简单易学的编程语言,语法简洁而清晰,并且拥有丰富和强大的类库。与其它大多数程序设计语言使用大括号不一样 ,它使用缩进来定义语句块。

在平时的工作中,Python开发者很容易犯一些小错误,这些错误都很容易避免,本文总结了Python开发者最常犯的10个错误,一起来看下,不知你中枪了没有。


1.滥用表达式作为函数参数默认值

Python允许开发者指定一个默认值给函数参数,虽然这是该语言的一个特征,但当参数可变时,很容易导致混乱,例如,下面这段函数定义:

>>> def foo(bar=[]):        # bar is optional and defaults to [] if not specified...    bar.append("baz")    # but this line could be problematic, as we'll see......    return bar

在上面这段代码里,一旦重复调用foo()函数(没有指定一个bar参数),那么将一直返回'bar',因为没有指定参数,那么foo()每次被调用的时候,都会赋予[]。下面来看看,这样做的结果:

>>> foo()["baz"]>>> foo()["baz", "baz"]>>> foo()["baz", "baz", "baz"]
解决方案:

>>> def foo(bar=None):...    if bar is None:		# or if not bar:...        bar = []...    bar.append("baz")...    return bar...>>> foo()["baz"]>>> foo()["baz"]>>> foo()["baz"]
2.错误地使用类变量

先看下面这个例子:

>>> class A(object):...     x = 1...>>> class B(A):...     pass...>>> class C(A):...     pass...>>> print A.x, B.x, C.x1 1 1
这样是有意义的:

>>> B.x = 2>>> print A.x, B.x, C.x1 2 1
再来一遍:

>>> A.x = 3>>> print A.x, B.x, C.x3 2 3
仅仅是改变了A.x,为什么C.x也跟着改变了。

在Python中,类变量都是作为字典进行内部处理的,并且遵循方法解析顺序(MRO)。在上面这段代码中,因为属性x没有在类C中发现,它会查找它的基类(在上面例子中只有A,尽管Python支持多继承)。换句话说,就是C自己没有x属性,独立于A,因此,引用 C.x其实就是引用A.x。

3.为异常指定不正确的参数

假设代码中有如下代码:

>>> try:...     l = ["a", "b"]...     int(l[2])... except ValueError, IndexError:  # To catch both exceptions, right?...     pass...Traceback (most recent call last):  File "<stdin>", line 3, in <module>IndexError: list index out of range

问题在这里,except语句并不需要这种方式来指定异常列表。然而,在Python 2.x中,except Exception,e通常是用来绑定异常里的 第二参数,好让其进行更进一步的检查。因此,在上面这段代码里,IndexError异常并没有被except语句捕获,异常最后被绑定 到了一个名叫IndexError的参数上。

在一个异常语句里捕获多个异常的正确方法是指定第一个参数作为一个元组,该元组包含所有被捕获的异常。与此同时,使用as关键字来保证最大的可移植性,Python 2和Python 3都支持该语法。

>>> try:...     l = ["a", "b"]...     int(l[2])... except (ValueError, IndexError) as e:  ...     pass...>>>
4.误解Python规则范围

Python的作用域解析是基于LEGB规则,分别是Local、Enclosing、Global、Built-in。实际上,这种解析方法也有一些玄机,看下面这个例子:

>>> x = 10>>> def foo():...     x += 1...     print x...>>> foo()Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "<stdin>", line 2, in fooUnboundLocalError: local variable 'x' referenced before assignment

许多人会感动惊讶,当他们在工作的函数体里添加一个参数语句,会在先前工作的代码里报UnboundLocalError错误( 点击这里查看更详细描述)。

在使用列表时,开发者是很容易犯这种错误的,看看下面这个例子:

>>> lst = [1, 2, 3]>>> def foo1():...     lst.append(5)   # This works ok......>>> foo1()>>> lst[1, 2, 3, 5]>>> lst = [1, 2, 3]>>> def foo2():...     lst += [5]      # ... but this bombs!...>>> foo2()Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "<stdin>", line 2, in fooUnboundLocalError: local variable 'lst' referenced before assignment
为什么foo2失败而foo1运行正常?

答案与前面那个例子是一样的,但又有一些微妙之处。foo1没有赋值给lst,而foo2赋值了。lst += [5]实际上就是lst = lst + [5],试图给lst赋值(因此,假设Python是在局部作用域里)。然而,我们正在寻找指定给lst的值是基于lst本身,其实尚未确定。

5.修改遍历列表

下面这段代码很明显是错误的:

>>> odd = lambda x : bool(x % 2)>>> numbers = [n for n in range(10)]>>> for i in range(len(numbers)):...     if odd(numbers[i]):...         del numbers[i]  # BAD: Deleting item from a list while iterating over it...Traceback (most recent call last):  	  File "<stdin>", line 2, in <module>IndexError: list index out of range
在遍历的时候,对列表进行删除操作,这是很低级的错误。稍微有点经验的人都不会犯。

对上面的代码进行修改,正确地执行:

>>> odd = lambda x : bool(x % 2)>>> numbers = [n for n in range(10)]>>> numbers[:] = [n for n in numbers if not odd(n)]  # ahh, the beauty of it all>>> numbers[0, 2, 4, 6, 8]
6.如何在闭包中绑定变量

看下面这个例子:

>>> def create_multipliers():...     return [lambda x : i * x for i in range(5)]>>> for multiplier in create_multipliers():...     print multiplier(2)...
你期望的结果是:

<code>02468</code>
实际上:

<code>88888</code>
是不是非常吃惊!出现这种情况主要是因为Python的后期绑定行为,该变量在闭包中使用的同时,内部函数又在调用它。

解决方案:

>>> def create_multipliers():...     return [lambda x, i=i : i * x for i in range(5)]...>>> for multiplier in create_multipliers():...     print multiplier(2)...02468
7.创建循环模块依赖关系

假设有两个文件,a.py和b.py,然后各自导入,如下:

在a.py中:

import bdef f():    return b.x	print f()
在b.py中:

import ax = 1def g():    print a.f()
首先,让我们试着导入a.py:

<code>>>> import a1</code>

可以很好地工作,也许你会感到惊讶。毕竟,我们确实在这里做了一个循环导入,难道不应该有点问题吗?

仅仅存在一个循环导入并不是Python本身问题,如果一个模块被导入,Python就不会试图重新导入。根据这一点,每个模块在试图访问函数或变量时,可能会在运行时遇到些问题。

当我们试图导入b.py会发生什么(先前没有导入a.py):

>>> import bTraceback (most recent call last):  	  File "<stdin>", line 1, in <module>  	  File "b.py", line 1, in <module>    import a  	  File "a.py", line 6, in <module>	print f()  	  File "a.py", line 4, in f	return b.xAttributeError: 'module' object has no attribute 'x'

出错了,这里的问题是,在导入b.py的过程中还要试图导入a.py,这样就要调用f(),并且试图访问b.x。但是b.x并未被定义。

可以这样解决,仅仅修改b.py导入到a.py中的g()函数:

x = 1def g():    import a	# This will be evaluated only when g() is called    print a.f()
无论何时导入,一切都可以正常运行:

>>> import b>>> b.g()1	# Printed a first time since module 'a' calls 'print f()' at the end1	# Printed a second time, this one is our call to 'g'
8.与Python标准库模块名称冲突

Python拥有非常丰富的模块库,并且支持“开箱即用”。因此,如果不刻意避免,很容易发生命名冲突事件。例如,在你的代码中可能有一个email.py的模块,由于名称一致,它很有可能与Python自带的标准库模块发生冲突。

9.未按规定处理Python2.x和Python3.x之间的区别

看一下foo.py:

import sysdef bar(i):    if i == 1:        raise KeyError(1)    if i == 2:        raise ValueError(2)def bad():    e = None    try:        bar(int(sys.argv[1]))    except KeyError as e:        print('key error')    except ValueError as e:        print('value error')    print(e)bad()
在Python 2里面可以很好地运行:

$ python foo.py 1key error1$ python foo.py 2value error2
但是在Python 3里:

$ python3 foo.py 1key errorTraceback (most recent call last):  File "foo.py", line 19, in <module>    bad()  File "foo.py", line 17, in bad    print(e)UnboundLocalError: local variable 'e' referenced before assignment
解决方案:

import sysdef bar(i):    if i == 1:        raise KeyError(1)    if i == 2:        raise ValueError(2)def good():    exception = None    try:        bar(int(sys.argv[1]))    except KeyError as e:        exception = e        print('key error')    except ValueError as e:        exception = e        print('value error')    print(exception)good()
在Py3k中运行结果:

<code>$ python3 foo.py 1key error1$ python3 foo.py 2value error2</code>
在 Python招聘指南里有许多关于Python 2与Python 3在移植代码时需要关注的注意事项与讨论,大家可以前往看看。

10.滥用__del__方法

比如这里有一个叫mod.py的文件:

import fooclass Bar(object):   	    ...    def __del__(self):        foo.cleanup(self.myhandle)
下面,你在another_mod.py文件里执行如下操作:

import modmybar = mod.Bar()
你会获得一个AttributeError异常。

至于为什么会出现该异常,点击这里查看详情。当解释器关闭时,该模块的全局变量全部设置为None。因此,在上面这个例子里,当__del__被调用时,foo已经全部被设置为None。

一个很好的解决办法是使用atexit.register()代替。顺便说一句,当程序执行完成后,您注册的处理程序会在解释器关闭之前停止 工作。

修复上面问题的代码:

import fooimport atexitdef cleanup(handle):    foo.cleanup(handle)class Bar(object):    def __init__(self):        ...        atexit.register(cleanup, self.myhandle)
在程序的正常终止的前提下,这个实现提供了一个整洁可靠的方式调用任何需要清理的功能。

总结

顶尖技术人员“兜售”的顶尖编程语言、扩展工具等 移动阅读商业化:Flipboard支持用户DIY杂志 全球移动App:Top 52发行商排行榜 知新网CTO:从程序员的视角,实践精益创业 罗永浩锤子ROM:小团队的75项微创新 谷歌知识图谱扩展到Android平板电影中 云计算大战升温 服务器OEM押注OpenStack 如何将战略性的内容策略融入进网页设计中 数字天堂CTO:移动行业应用开发“潜规则” 众联智领CTO:从idea到面目全非的创业产品 CMDN Club 25期:knewone与路况电台的精益创业法则 Windows Blue的孪生兄弟?Office Gemini浮出水面 HTML5开发平台Ludei将支持3D游戏开发 《二战风云》发布至今,已为顽石互动狂赚2.7亿 腾讯开源基于HTML5技术的专业级图像处理引擎 AlloyImage Linux容器运行时Docker开源 360上线第三方漏洞收录平台 将现金奖励爆料者 UC推出iOS平台首个支持WebGL的浏览器 魔兽之父专访:今年游戏产业会出现一场革命 Instagram 5位传奇工程师背后的技术(PPT全译) Google云计算专家Jeff Dean与Sanjay Ghemawat获ACM Infosys基金会大奖 谷歌承诺不对开发、发行和使用开源软件的人专利诉讼 Web框架排行榜 Netty、Servlet和Vert.x位列前三 DARPA慷慨解囊的背后:Python与大数据的火花 研发周报:神奇!1KB JavaScript代码编写的3D蜜蜂 移动周报:65岁传奇Android工程师谈开发 “部落战争”开发商Supercell融资1亿美金 投资公司争先恐后 Kiip 90后华裔励志故事:从遭解雇到誉满全球 大数据基因测序的成本逼近1000美元:个性化医疗的时代来临 携程开放平台发力 将实现旗下产品全流程API支持 Puppet labs发布2013自动化运维报告 ============答对我的问题者,将可获得111222的签名照片!!!!!!!!=========== 关于图片的上传 ======== 绝对好消息,activereport2.0已经release 了,cracker们出动啊~~~~~加油 ============= 关于什么才是真正的系统分析和系统分析员的讨论!——欢迎大家参加,进行善意地讨论!^&^ 今晚的球赛什么时候开始啊? 哪里有关于水平考试(高程)的模拟题的啊??? 为什麽还是不能显示中文呢? 怎样获取WIN2000的密码 在父窗体怎样画jpg格式的背景图? 如何注册MSComm控件????????? 如何解决这个问题啊?重赏啊!!!! 公告: 从现在开始封shines 111222 :)流芳斑主,结贴的工作要开始了,会很累啊!我代表大家先谢谢你了! 怎样改变MSHflexgrid中每条记录的背景颜色。急急急急急急急 各位,能不能给我讲一下“句柄”是怎么一回事? 唉,心情不爽 关于C++语法的问题? 灌水-----大学时的恶作剧(转载) "setdibs()"是什么来着,请指教,谢谢! 写注释不宜过头 这段代码错在哪里? 请大家预测一下比分(参与者都有分)开赛后就不算了,还有半个小时,赶紧着 写网络电话程序的讨论 最后一帖,贴完睡觉----如何在电梯里捣乱 怎样定制一个在程序中重用的组件?只能通过包方式吗? 寻寻觅觅 汉英计算机科技文章 互译!!有劳各位朋友费心帮忙找找 我靠!真TMD不爽,这个时候准老婆的老妈进了医院! 怎样调用*.db格式文件 谁知道哪儿有英汉互译,急急急急!!!! ISO 9001认证 VS CMM2 谁知道哪儿有《神秘的人月》下载? 为111222求情 怎样可以修改浏览器的标题? 怎样可以修改浏览器的标题1? 哪位能给我一个source insight 3.0的sn号? 怎样可以修改浏览器的标题2? 如何异步调用远程组件的方法? 哈哈!球赛开始了!我也不想去医院了!!!顶多明天挨顿骂! 上CSDN的有谁是七月份毕业,大家认识一下 我想问问,一个程序员的黄金年龄是多少? 如何由CRgn得到一组Polygon? 初学者请教一个小问题!急急急,尿都快急出来啦! 急急急急急急急急急急,用vb怎样知道COM口是不是打开着,能不能不用控件高分. 高手请看:20 分 我想给50 分,但是系统只让给20分,对不起大家了,有机会一定补上!!! 关于一个报表问题,急! 我需要一个Hackman的配套的Debugger,有谁知道哪有 现在就用VB.net开发商用程序可靠吗? 急急急急急急急急急急,用vb怎样知道COM口是不是打开着,能不能不用控件,怎样用API函数,高分。 中乌最新战报!!!!!!!!!! .....百丑图..... 高手请推荐几本好的C的书,华储里都是C++,C才几本而已。 ..二元一次方程组...有一些苹果箱,若每只装苹果25千克,则剩余40千克无处装,若每只装30千克,则余20只空箱,这些苹果箱有多少只?请列式计算...PS...符号"^"表示上标..即N次方...每个方程组之间请 设方程2^x+x+2=0和方程log2 x+x+2=0的根分别为p和q,则p+q=?我想知道,作出y=2^x,y=log2 x,及y=-x-2的图像以后, 初一计算题解方程 分母带小数的或去分母的 列二元一次方程组解2道初中数学题1,一旅馆的客房有3人间和2人间,3人间每人每晚25元,2人间每人每晚35元.一个50人的旅游团到该旅馆住宿,租住了若干客房且每个客房正好住满,一天共花住宿费1 已知方程2^x+x+2=0的根为P,log2(x+x+2)=0的根为q,记f(x)=(x+p)(x+q)+2则A,f(0) 求20到方程(十道去分母)不要应用题10道去分母 10到化简求值 10道随便 (要求不带答案,不是应用题)来的及时有悬赏! 初中数学二元一次方程组题一个两位数,个位数字比十位数字大5.如果把个位数字对调,那么所得到的新数与原来数的和是143.求原来的两位数 2x-3/4=5/6 . 关于方程去分母的计算题5道. 初中数学题(有关二元一次方程组~急)1.若|X+Y-3|+(X-Y)^2=0,你能求出X,2.已知t满足方程组{2x=3-5t,则x和y之间满足的关系式是_______3y-2t=x, 6.3-2x+4.5=7. 方程3分之2x-1=6分之2x-1 -1去分母得________ 初中数学题二元一次方程组 解答两道方程题目(1)3x²=2x (2) (x+4)²=5(x+4)(1)3x²=2x (2) (x+4)²=5(x+4) 这个方程怎么解 3分之2X-1=0.5 方程log2 (x+4)=2^x的实数根的个数为好像是两解 请根据方程,x+2x+3x=72联系生活实际,编一道应用题(要求题目完整,题意清楚)明天就要交 试求方程x^2-2x-4|x-1|+4=0的四个根之和,当1<b<5时,再求方程x^2-2x-4|x-1|+b=0的四个根之和 方程log2(x+4)=3^x的实数根的个数为 编写一道应用题,使它满足下列要求:1:题意适合一元一次方程2x+8=6-2x 2:所编应用题应完整,符合实际. 已知x=1是方程2-3分之1(a-x)=2x的解,求关于y的方程a(y-5)-2=a(2y-3)的解 方程log2(x+3)=3的x次方的实数根的个数 8道一元一次方程应用题先说明要有步骤不要只有一个答案 不用再步骤中插入解说。一定要用方程!1、两个仓库装粮食,第一个仓库是第二个仓库存粮的3倍,如果从第一个仓库中取出20吨放 8x-3=13,0.3x+0.4=0.7x-0.1,4x-5=9/2x-4 ,y-1/2+3=y+12/3-1 判断方程Log2(x)+x^2=0在区间[1/2,1]内有没有实数根,为什么? 求一元一次方程答案 2x-1/6=5x+1/8带步骤的速度要快 当K为何整数时,方程组2X+Y=K和X+3Y=6的解是非负数 方程log2 (x+4)=(1∕2)^x的实数根的个数为答案为1个数 不用画图能做吗!最好不要画图能做! 求30-40道初一的一元一次方程练习题!不要应用题,像2x+1=x+3这种题不要 当K为何值时,方程组:2x+y=k x+3y=6的解是非负数看不懂 能说清楚点吗? 方程ln(3*2^x-2)=log2的3+log2的1/3d的解为 解下列方程:2x+3y=4,3x-2y=11. 已知关于x、y的方程组2x+y=-7-a.x-3y=10a中,x是非负数,y是负数,求a的取值范围 方程log2(2^x+1)log2(2^(x+1)+2)=2的解为 要具体方程log2(2^x+1)log2(2^(x+1)+2)=2的解为 要具体过程 3x-2y=8,2x+3y=7 用加减消元法解这个方程 M为何数时,方程X+Y=M,5X+3Y=13的解是非负数? 方程log2(9ˇx-5)=log2(3ˇx-2)+2的解集是过程理由 已知3x+2y=17,2x+3y=13,则x-y=( ).方程2x+y=6的正整数解是( ) 已知关于x,y的方程级x+y=k 5x+3y=31的解xy均是非负数,求整数k的值用一元一次不等式解 x^log2(x+2)=8 解对数方程, 3x-2y=6 2x+3y=17 解方程 某项工程由甲队独做需要40天完成,如果由乙队先单独做10天,那么剩下的工程两队合作20天才完成 1求乙队单独完成这项工程所需的天数.2求两队合作完成这项工程所需的天数 求方程log2(x+4)=(1/3)^x的根的个数,并说明理由给点思路也行..请误乱写P言 省得没人问津 以为有人答了.] 0.01分之4-6x-6.5=0.02分之0.02+2x-7.5 已知关于x的方程2x-a/3-x-a/2=x-1与方程3(x-2)=4x-5有相同的解,求a的值实在搞不懂 方程log2(x+5)=4^x的实根的个数为RT!求教! 已知关与X的方程.2分之2M+X=4的解是方程3分之2X-3M-4分之X-1=6X-1的解的5 倍求这两个方程的解. 已知关于x的方程(2x-a)/3-(2-a)/2=x-1与方程3(x-2)=4x-5有相同的解,求a的值 7.8-x=6.2这个方程怎么解 方程log2(x+a)=3^x的实根的个数A.0B.1C.2D.3 (0.1x-0.2)/0.01-6.5=(0.02-2x)/0.02-7.5 解方程 第6、7题用列方程解决. 方程log2(x+4)=x^(1/3)根的个数是几个 (4-6x)/0.01-6.5+(0.02-2x)/0.02-7.5(注意解方程按步骤先通分再去分母再移向的做法)sorry……(4-6x)/0.01-6.5=(0.02-2x)/0.02-7.5 6、7、8题怎么做直接列方程不用解 方程log2(2^x+1)log2(2^(x+1)+2)=2的解 解方程4-6x/0.01+1=0.02-2x/0.02和2|2x-1|+1=5 七年级上册数学复习题3答案 速度好急快啊要方程的式子 和答案 6.7.8.9题要过程 急 速度速度速度速度速 方程log2(2^x+1)log2(2^(x+1)+2)=2的解为给答案就行 (3+0.2x)/0.2-(0.2+0.03x)/0.01=0.75 解方程
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn