python编程培训中常见错误
最后,我想谈谈使用更多python函数(数据类型、函数、模块、类等)时可能遇到的问题。由于篇幅有限,我们试图将其简化,特别是一些高级概念。有关更多详细信息,请阅读学习python、第二版的“技巧”和“gotchas”章节。
打开文件的调用不使用模块搜索路径
在python中调用open()访问外部文件时,python不使用模块搜索路径来定位目标文件。它将使用您提供的绝对路径,或者假定文件位于当前工作目录中。模块搜索路径仅用于模块加载。
不同的类型对应不同的方法。
列表方法不能用于字符串,反之亦然。通常,方法调用与数据类型相关,但内部函数通常在许多类型上可用。例如,list的reverse方法只对list有用,但是len函数对任何有长度的对象都有效。
无法直接更改不可变数据类型
请记住,不能直接更改不可变对象(例如元组、字符串):
t=1、2、3
t[2]=4误差
用切片、连接等构造一个新的对象,并根据需要为其分配原始变量的值。因为python会自动回收无用的内存,所以并不像看起来那么浪费:
t=t[:2]+(4,)没问题:t变成(1,2,4)
使用简单for循环而不是while或range
当您从左到右遍历有序对象的所有元素时,使用简单的for循环(例如,seq:中的x)比使用基于while或range的计数循环更容易编写,并且通常运行得更快。除非需要,否则请尽量避免在for循环中使用range:让python为您解决标记问题。在下面的示例中,这三个循环都很好,但第一个循环通常更好;在python中,简单性是最重要的。
S=伐木工人
对于c in s:print c是最简单的
对于范围内的i(len(s):打印s[i]太多
I=0太多
当i<len(s):打印s[i];i+=1
不要试图从更改对象的函数中获取结果。
直接更改操作,如方法列表。追加()并列出。sort()更改对象,但不返回更改的对象(它们不返回任何对象);正确的方法是直接调用它们,而不是分配结果。经常看到初学者编写这样的代码:
mylist=我的列表。附加(X)
目标是获取追加结果,但实际上这样做不会将任何结果分配给mylist,而不是已更改的列表。一个更具体的例子是按排序的键值遍历字典的元素。请参见以下示例:
D={…}
对于K in d.键()。排序():打印d[k]
几乎成功了——keys方法创建了一个键列表,并使用sort方法对列表进行排序——但是由于sort方法返回none,因此循环失败,因为它实际上遍历了none(这不是序列)。若要更正此代码,请将方法调用分离并将它们放在不同的语句中,如下所示:
ks=d.键()
堪萨斯州。排序()
对于k in ks:打印d[k]
类型转换仅存在于数值类型中
在python中,像123+3.145这样的表达式可以工作——它自动将整数转换为浮点类型,然后使用浮点操作。但以下代码会出错:
S=42
I=1
X=S+I类型错误
这也是有意的,因为不清楚是将字符串转换为数字(add)还是将数字转换为字符串(join)?在python中,我们认为“清晰优于模糊”(即eibti(显式优于隐式),因此必须手动转换类型:
X=int(s)+i加法:43
x=s+str(i)字符串连接:“421”
循环的数据结构导致循环
虽然这在实践中很少见,但如果对象集合包含自己的引用,则称为循环对象。如果在对象中找到循环,python将输出一个[……]为了避免陷入无限循环:
“>l=['grail']在l中指l本身
l.append(l)在对象中创建循环
>一
圣杯,[…]]
除了知道这三个点表示对象中的循环之外,这个示例也值得学习。因为您可能会无意中在代码中出现这样的循环结构并导致代码出错。如有必要,请维护一个列表或字典来表示已访问的对象,然后检查它是否遇到循环。
赋值语句不创建对象的副本,只创建引用
这是python的核心概念之一,当事情出错时,有时会导致错误。在下面的例子中,list对象被分配给一个名为l的变量,然后在清单m中引用这个变量。在内部更改l也会更改m引用的对象,因为它们都指向同一个对象。
>L=1,2,3]公共列表对象
python是一种面向对象的语言,所以程序抛出的异常是类。有几个常见的python异常。你只需要看一眼,然后有一个形象。当你编程时,你肯定会遇到他们不止一次(除非你不需要python)。
异常描述
nameerror试图访问未声明的变量
零分误差除法器为0
语法错误语法错误语法错误语法错误语法错误语法错误语法错误语法错误语法错误语法错误语法错误语法错误语法错误语法错误语法错误语法错误语法错误语法错误语法错误
索引器错误索引超出序列范围
keyerror请求不存在的dictionary关键字
IOERROR输入和输出错误(例如,要读取的文件不存在)
AttributeRor尝试访问未知对象属性
valueerror将不正确的参数类型传递给函数,例如将输入字符串传递给int()函数。
2.捕捉异常
python捕获异常的完整语句有点像:
复制代码如下:
尝试:
试衣间
异常1,异常2,…,参数:
例外套房
…
其他:
未检测到任何异常套件
最后:
始终执行套件
是不是很复杂?当然,当我们想要捕捉异常时,我们不必像上面那样用同样的格式写下它们。我们可以抛出else语句或final语句;甚至可以留下final语句而不是exception语句。嗯,晕倒?好吧,接下来,让我们解释一下。
2.1条。尝试。。。除了…陈述
不必说,正如大家所知,try_suite是我们捕获异常所需的代码。except语句是关键。在try_suite中捕获异常后,除了处理之外,我们将把它交给。
最简单的尝试…但声明如下:
复制代码如下:
尝试:
试衣间
除外:
异常块
上面的except子句不跟随任何异常和异常参数,因此无论try捕获到什么异常,都将由except子句的异常块处理。如果我们想处理特定的异常,例如,我们只想处理除零的异常,如果发生其他异常,让它们被抛出而不被处理,会怎么样?此时,我们将在except子句中传递一个异常参数!exceptionn是我们要给except子句的异常类(请参见exception类的表),这意味着如果捕捉到此类异常,它们将由except子句处理。例如:
复制代码如下:
尝试:
试衣间
例外情况:
异常块
例如:
复制代码如下:
“>尝试:
res=2/0
除零除错误外:
打印“错误:除数不能为零!”
…
错误:除数不能为零!
看,我们真的抓到了零除错误异常!那么如果我想捕获和处理多个异常呢?有两种方法,一种是将多个异常类参数传递给一个except子句,另一种是编写多个except子句,每个子句都传递给要处理的异常类参数。甚至,这两种用法也可以混为一谈!_______我给你举个例子。
复制代码如下:
尝试:
floatnum=float(原始输入(“请输入浮点:”)
intnum=int(浮点数)
打印100/IntNum
除零除错误外:
print“错误:必须输入大于或等于1的浮点数!”
除了valueerror:
print“错误:必须输入浮点数!”
[根@prehive tmp]python test.py
请输入浮点:fjia
错误:必须输入浮点数!
[根@prehive tmp]python test.py
请输入浮点数:0.9999
错误:必须输入大于或等于1的浮点数!
[根@prehive tmp]python test.py
请输入浮点数:25.091
4个
一旦你能理解以上的例子,你就不再解释了。只要您理解,我们的except可以处理一个异常,许多异常,甚至所有异常。
正如你可能已经注意到的,我们还没有解释except子句后面的论点。别担心,一个接一个听我说。这个参数实际上是一个异常类的实例(不要告诉我你不知道什么是实例),它包含来自异常代码的诊断信息。也就是说,如果捕捉到异常,可以通过异常类的实例获取有关异常的更多信息。例如:
复制代码如下:
“>尝试:
1/0号
除零除错误外,原因:
…通过
…
“>类型(原因)
<type'exceptions.zero division error'>
打印原因
整数除零或模零
原因>
零除错误('整数除或模乘零',)
原因。_阶级__
<type'exceptions.zero division error'>
原因。类文档__
“除法或模运算的第二个参数为零。”
“>原因。类名__
'零除错误'
在上面的例子中,我们捕获到一个被零除的异常,但是什么也没做。这个原因是异常类ZeroDivisionError的一个实例,您可以通过类型看到。