您所在的位置: &
17个新手常见Python运行时错误(2)
17个新手常见Python运行时错误(2)
当初学 Python 时,想要弄懂 Python 的错误信息的含义可能有点复杂。这里列出了常见的的一些让你程序 crash 的运行时错误。
11)使用不存在的字典键值(导致&KeyError:&spam&&)
该错误发生在如下代码中:
spam&=&{'cat':&'Zophie',&'dog':&'Basil',&'mouse':&'Whiskers'} &print('The&name&of&my&pet&zebra&is&'&+&spam['zebra'])&
12)尝试使用Python关键字作为变量名(导致&SyntaxError:invalid syntax&)
Python关键不能用作变量名,该错误发生在如下代码中:
class&=&'algebra'&
Python3的关键字有:and, as, assert, break, class, continue, def, del, elif, else, except, False, finally, for, from, global, if, import, in, is, lambda, None, nonlocal, not, or, pass, raise, return, True, try, while, with, yield
13)在一个定义新变量中使用增值操作符(导致&NameError: name 'foobar' is not defined&)
不要在声明变量时使用0或者空字符串作为初始值,这样使用自增操作符的一句spam += 1等于spam = spam + 1,这意味着spam需要指定一个有效的初始值。
该错误发生在如下代码中:
spam&=&0&spam&+=&42&eggs&+=&42&
14)在定义局部变量前在函数中使用局部变量(此时有与局部变量同名的全局变量存在)(导致&UnboundLocalError: local variable 'foobar' referenced before assignment&)
在函数中使用局部变来那个而同时又存在同名全局变量时是很复杂的,使用规则是:如果在函数中定义了任何东西,如果它只是在函数中使用那它就是局部的,反之就是全局变量。
这意味着你不能在定义它之前把它当全局变量在函数中使用。
该错误发生在如下代码中:
someVar&=&42&def&myFunction(): &&&&&print(someVar) &&&&&someVar&=&100&myFunction()&
15)尝试使用 range()创建整数列表(导致&TypeError: 'range' object does not support item assignment&)
有时你想要得到一个有序的整数列表,所以 range() 看上去是生成此列表的不错方式。然而,你需要记住 range() 返回的是 &range object&,而不是实际的 list 值。
该错误发生在如下代码中:
spam&=&range(10) &spam[4]&=&-1&
也许这才是你想做:
spam&=&list(range(10)) &spam[4]&=&-1&
(注意:在 Python 2 中 spam = range(10) 是能行的,因为在 Python 2 中 range() 返回的是list值,但是在 Python 3 中就会产生以上错误)
16)不错在 ++ 或者 -- 自增自减操作符。(导致&SyntaxError: invalid syntax&)
如果你习惯于例如 C++ , Java , PHP 等其他的语言,也许你会想要尝试使用 ++ 或者 -- 自增自减一个变量。在Python中是没有这样的操作符的。
该错误发生在如下代码中:
spam&=&1 &spam++&
也许这才是你想做的:
spam&=&1&spam&+=&1&
17)忘记为方法的第一个参数添加self参数(导致&TypeError: myMethod() takes no arguments (1 given)&)
该错误发生在如下代码中:
class&Foo(): &&&&&def&myMethod(): &&&&&&&&&print('Hello!') &a&=&Foo() &a.myMethod()&
原文链接:
【编辑推荐】
【责任编辑: TEL:(010)】
内容导航&第 1 页: &第 2 页:
关于的更多文章
Python是"一种解释型的、面向对象的、带有动态语义的高级程序设
网友评论TOP5
随着云计算、物联网、大数据、移动互联网的大发展,你应该知道这些。
平年的9月13日和闰年的9月12日(每年的第256天)是程
移动互联网的投资机会到底还有哪些?移动互联网的下一
即将进入程序员这支队伍的大学生不在少数,你是否在即
本书从计算机网络安全的概念入手,分析了单机节点、单一网络、互联网络和开放互联网络的基本安全问题,并对计算机网络安全体系架
51CTO旗下网站Python开发丨如果你是python新手,千万别犯这些错误
Python开发丨如果你是python新手,千万别犯这些错误
印象步步为王
在学习python初期,往往会犯一些错误,这些错误是不自知的,但是早早了解了这些,比犯了错后才明白好的多。这里就总结了python新手常常遇到的问题。1.不知道Python版本这是一个在StackOverflow上反复出现的问题。许多人能写出在某个版本上完美工作的代码,但在他们在自己的系统上***有不同版本的Python。要确保你知道你正在使用的Python版本。你可以通过下边的代码查看Python版本:[pythontab@testServer]$ python--versionPython2.7.10[pythontab@testServer]$ python--V上面两种方法都是可以的2.不使用版本管理器pyenv是一个极好的管理不同Python版本的工具,但很不幸,它只工作在*nix系统上。在Mac系统上,你可以简单地通过brew install pyenv***它,在Linux上,也有一个自动***程序。3.沉迷于一行程序许多人热衷于一行程序带来的兴奋感。即使他们的一行解决方案比一个多行解决方案低效,他们也会吹嘘。Python中的一行程序在本质上意味着具有多个表达式的复杂推导。例如:l=[mfora, binzip(this, that)ifb.method(a) !=bforminbifnotm.method(a, b)老实讲,我编造了上面的例子。但我看到很多人都写类似的代码。这样的代码在一个星期后就会变得难以理解。如果你想做一些稍微复杂的事情,例如根据条件简单地在一个列表或集合中添加一个元素,你可能就会犯错误。单行代码并不是什么成就,是的,他们可能看起来很灵活,但不是什么成就。想象一下,这就像是你在打扫房间时把所有的东西都塞进你的衣橱。好的代码应该是干净的,易于阅读的和高效的。4.利用错误的方式初始化一个集合这是一个更微妙的问题,可能让你措手不及。集合推导很像列表推导。&&& { nforninrange(10)ifn%2==0}{0,8,2,4,6}&&&type({ nforninrange(10)ifn%2==0})上面就是集合推导的一个例子。集合就像列表,也是一个容器。所不同的是,一个集合中不能有任何重复的值,而且是无序的。看到集合推导人们经常错误地认为{}能初始化一个空集合。但其实不然,它初始化一个空字典。&&& {}{}&&&type({})如果你想初始化一个空集合,可以简单地调用set()方法。&&&set()set()&&&type(set())注意一个空集合用set()表示,但是一个包含一些元素的集合就就要用花括号包围元素来表示。&&& s=set()&&& s&&& s.add(1){1}&&& s.add(2){1,2}这和直觉是相反的,因为你期望类似于set([1, 2])的一些东西。5.误解GILGIL(全局解释器锁)意味着在Python程序中,任意一个时间点只能有一个线程在运行。这意味着当我们创建一个线程并希望它并行运行时,它并不会那样。Python解释器实际的工作是在不同的运行线程之间快速进行切换。但这只是对实际发生事情的一个非常简单的解释,实际情况要复杂的多。有很多种并行运行的实例,例如使用本质为C扩展的各种库。但运行Python代码时,大部分时间里它不会并行执行。换句话说,Python中的线程并不像Java或C++中的线程。许多人会尝试为Python辩解,说这些都是真正的线程。这确实是真的,但并不能改变这样一个事实:Python处理线程的方式和你期望的方式是不同的。Ruby语言也有相同的情况(Ruby也有一个解释器锁)。指定的解决方案是使用multiprocessing模块。multiprocessing模块提供Process类,它是一个对fork的很好的覆盖。然而,fork过程比一个线程的代价高得多,所以你可能不会每次都能看到性能上的提升,因为不同的process之间需要做大量的工作来进行相互协调。然而,这个问题并不存在于每一个Python的实现版本中。例如,Python的一个实现PyPy-stm就试图摆脱GIL(仍未稳定)。建立在其他平台,如JVM(Jython)或CLR(IronPython),上的Python实现,也没有GIL的问题。总之,使用Thread类时要多加小心,你得到的可能不是你想要的。6.使用旧式类在Python 2中,有两种类型的类,分别为“旧式”类和“新式”类。如果你使用Python 3,那么你默认使用“新式”类。为了确保在Python2中使用“新式”类,你需要让你新创建的每一个类都继承object类,且类不能已继承了内置类型,例如int或list。换句话说,你的基类、类如果不继承其他类,就总是需要继承object类。classMyNewObject(object):# stuff here这些“新式”类解决一些老式类的根本缺陷,想要详细了解新式类和旧式类请参见《python新式类和旧式类区别》《python2中的__new__与__init__,新式类和经典类》。7.按错误的方式迭代对于这门语言的新手来说,下边的代码是非常常见的:forname_indexinrange(len(names)):print(names[name_index])在上边的例子中,没有必须调用len函数,因为列表迭代实际上要简单得多:fornameinnames:print(name)此外,还有一大堆其他的工具帮助你简化迭代。例如,可以使用zip同时遍历两个列表:forcat, doginzip(cats, dogs):print(cat, dog)如果你想同时考虑列表变量的索引和值,可以使用enumerate:forindex, catinenumerate(cats):print(cat, index)在itertools中也有很多有用的函数供你选择。然而请注意,使用itertools函数并不总是正确的选择。如果itertools中的一个函数为你试图解决的问题提供了一个非常方便的解决办法,例如铺平一个列表或根据给定的列表创建一个其内容的排列,那就用它吧。但是不要仅仅因为你想要它而去适应你代码的一部分。滥用itertools引发的问题出现的过于频繁,以至于在StackOverflow上一个德高望重的Python贡献者已经贡献他们资料的重要组成部分来解决这些问题。8.使用可变的默认参数我多次见到过如下的代码:deffoo(a, b, c=[]):# append to c# do some more stuff永远不要使用可变的默认参数,可以使用如下的代码代替:deffoo(a, b, c=None):ifcisNone:c=[]与其解释这个问题是什么,不如展示下使用可变默认参数的影响:&&&deffoo(a, b, c=[]):... c.append(a)... c.append(b)...print(c)...&&& foo(1,1)[1,1][1,1,1,1][1,1,1,1,1,1]同一个变量c在函数调用的每一次都被反复引用。这可能有一些意想不到的后果。以上这些问题都是新手常常会遇到的问题,但也并不仅仅只是这些,还有些人会用以前熟知的语言习惯来使用python,这也会造成很多问题。
本文仅代表作者观点,不代表百度立场。系作者授权百家号发表,未经许可不得转载。
印象步步为王
百家号 最近更新:
简介: 大道至简。极简、极素、极致、极速。
作者最新文章