python出错,请问是什么问题

 我来答
兄弟连教育
2018-08-01 · 百度知道合伙人官方认证企业
兄弟连教育
兄弟连教育成立于2006年,11年来专注IT职业教育,是国内专业的IT技术培训学校。2016年成功挂牌新三板(股票代码:839467)市值过亿。开设专注程序员培训专注php、Java、UI、云计算、Python、HTML5、
向TA提问
展开全部
要把代码发现来才知道,以下是常见的错误
下面终于要讲到当你用到更多的Python的功能(数据类型,函数,模块,类等等)时可能碰到的问题了。由于篇幅有限,这里尽量精简,尤其是对一些高级的概念。要想了解更多的细节,敬请阅读Learning Python, 2nd Edition的“小贴士”以及“Gotchas”章节。

打开文件的调用不使用模块搜索路径
当你在Python中调用open()来访问一个外部的文件时,Python不会使用模块搜索路径来定位这个目标文件。它会使用你提供的绝对路径,或者假定这个文件是在当前工作目录中。模块搜索路径仅仅为模块加载服务的。
不同的类型对应的方法也不同
列表的方法是不能用在字符串上的,反之亦然。通常情况下,方法的调用是和数据类型有关的,但是内部函数通常在很多类型上都可以使用。举个例子来说,列表的reverse方法仅仅对列表有用,但是len函数对任何具有长度的对象都适用
不能直接改变不可变数据类型
记住你没法直接的改变一个不可变的对象(例如,元组,字符串):

T = (1, 2, 3)
T[2] = 4 # 错误

用切片,联接等构建一个新的对象,并根据需求将原来变量的值赋给它。因为Python会自动回收没有用的内存,因此这没有看起来那么浪费:

T = T[:2] + (4,) # 没问题了: T 变成了 (1, 2, 4)

使用简单的for循环而不是while或者range
当你要从左到右遍历一个有序的对象的所有元素时,用简单的for循环(例如,for x in seq:)相比于基于while-或者range-的计数循环而言会更容易写,通常运行起来也更快。除非你一定需要,尽量避免在一个for循环里使用range:让Python来替你解决标号的问题。在下面的例子中三个循环结构都没有问题,但是第一个通常来说更好;在Python里,简单至上。

S = "lumberjack"

for c in S: print c # 最简单

for i in range(len(S)): print S[i] # 太多了

i = 0 # 太多了
while i < len(S): print S[i]; i += 1

不要试图从那些会改变对象的函数得到结果
诸如像方法list.append()和list.sort()一类的直接改变操作会改变一个对象,但不会将它们改变的对象返回出来(它们会返回None);正确的做法是直接调用它们而不要将结果赋值。经常会看见初学者会写诸如此类的代码:

mylist = mylist.append(X)

目的是要得到append的结果,但是事实上这样做会将None赋值给mylist,而不是改变后的列表。更加特别的一个例子是想通过用排序后的键值来遍历一个字典里的各个元素,请看下面的例子:

D = {...}
for k in D.keys().sort(): print D[k]

差一点儿就成功了——keys方法会创建一个keys的列表,然后用sort方法来将这个列表排序——但是因为sort方法会返回None,这个循环会失败,因为它实际上是要遍历None(这可不是一个序列)。要改正这段代码,将方法的调用分离出来,放在不同的语句中,如下:

Ks = D.keys()
Ks.sort()
for k in Ks: print D[k]

只有在数字类型中才存在类型转换
在Python中,一个诸如123+3.145的表达式是可以工作的——它会自动将整数型转换为浮点型,然后用浮点运算。但是下面的代码就会出错了:

S = "42"
I = 1
X = S + I # 类型错误

这同样也是有意而为的,因为这是不明确的:究竟是将字符串转换为数字(进行相加)呢,还是将数字转换为字符串(进行联接)呢?在Python中,我们认为“明确比含糊好”(即,EIBTI(Explicit is better than implicit)),因此你得手动转换类型:

X = int(S) + I # 做加法: 43
X = S + str(I) # 字符串联接: "421"

循环的数据结构会导致循环
尽管这在实际情况中很少见,但是如果一个对象的集合包含了到它自己的引用,这被称为循环对象(cyclic object)。如果在一个对象中发现一个循环,Python会输出一个[…],以避免在无限循环中卡住:

>>> L = ['grail'] # 在 L中又引用L自身会
>>> L.append(L) # 在对象中创造一个循环
>>> L
['grail', [...]]

除了知道这三个点在对象中表示循环以外,这个例子也是很值得借鉴的。因为你可能无意间在你的代码中出现这样的循环的结构而导致你的代码出错。如果有必要的话,维护一个列表或者字典来表示已经访问过的对象,然后通过检查它来确认你是否碰到了循环。
赋值语句不会创建对象的副本,仅仅创建引用
这是Python的一个核心理念,有时候当行为不对时会带来错误。在下面的例子中,一个列表对象被赋给了名为L的变量,然后L又在列表M中被引用。内部改变L的话,同时也会改变M所引用的对象,因为它们俩都指向同一个对象。

>>> L = [1, 2, 3] # 共用的列表对象
>>> M = ['X', L, 'Y'] # 嵌入一个到L的引用
>>> M
['X', [1, 2, 3], 'Y']

>>> L[1] = 0 # 也改变了M
>>> M
['X', [1, 0, 3], 'Y']

通常情况下只有在稍大一点的程序里这就显得很重要了,而且这些共用的引用通常确实是你需要的。如果不是的话,你可以明确的给他们创建一个副本来避免共用的引用;对于列表来说,你可以通过使用一个空列表的切片来创建一个顶层的副本:

>>> L = [1, 2, 3]
>>> M = ['X', L[:], 'Y'] # 嵌入一个L的副本

>>> L[1] = 0 # 仅仅改变了L,但是不影响M
>>> L
[1, 0, 3]
>>> M
['X', [1, 2, 3], 'Y']

切片的范围起始从默认的0到被切片的序列的最大长度。如果两者都省略掉了,那么切片会抽取该序列中的所有元素,并创造一个顶层的副本(一个新的,不被公用的对象)。对于字典来说,使用字典的dict.copy()方法。
静态识别本地域的变量名
Python默认将一个函数中赋值的变量名视作是本地域的,它们存在于该函数的作用域中并且仅仅在函数运行的时候才存在。从技术上讲,Python是在编译def代码时,去静态的识别本地变量,而不是在运行时碰到赋值的时候才识别到的。如果不理解这点的话,会引起人们的误解。比如,看看下面的例子,当你在一个引用之后给一个变量赋值会怎么样:

>>> X = 99
>>> def func():
... print X # 这个时候还不存在
... X = 88 # 在整个def中将X视作本地变量
...
>>> func( ) # 出错了!

你会得到一个“未定义变量名”的错误,但是其原因是很微妙的。当编译这则代码时,Python碰到给X赋值的语句时认为在这个函数中的任何地方X会被视作一个本地变量名。但是之后当真正运行这个函数时,执行print语句的时候,赋值语句还没有发生,这样Python便会报告一个“未定义变量名”的错误。
事实上,之前的这个例子想要做的事情是很模糊的:你是想要先输出那个全局的X,然后创建一个本地的X呢,还是说这是个程序的错误?如果你真的是想要输出这个全局的X,你需要将它在一个全局语句中声明它,或者通过包络模块的名字来引用它。
默认参数和可变对象
在执行def语句时,默认参数的值只被解析并保存一次,而不是每次在调用函数的时候。这通常是你想要的那样,但是因为默认值需要在每次调用时都保持同样对象,你在试图改变可变的默认值(mutable defaults)的时候可要小心了。例如,下面的函数中使用一个空的列表作为默认值,然后在之后每一次函数调用的时候改变它的值:

>>> def saver(x=[]): # 保存一个列表对象
... x.append(1) # 并每次调用的时候
... print x # 改变它的值
...
>>> saver([2]) # 未使用默认值
[2, 1]
>>> saver() # 使用默认值
[1]
>>> saver() # 每次调用都会增加!
[1, 1]
>>> saver()
[1, 1, 1]

有的人将这个视作Python的一个特点——因为可变的默认参数在每次函数调用时保持了它们的状态,它们能提供像C语言中静态本地函数变量的类似的一些功能。但是,当你第一次碰到它时会觉得这很奇怪,并且在Python中有更加简单的办法来在不同的调用之间保存状态(比如说类)。
要摆脱这样的行为,在函数开始的地方用切片或者方法来创建默认参数的副本,或者将默认值的表达式移到函数里面;只要每次函数调用时这些值在函数里,就会每次都得到一个新的对象:

>>> def saver(x=None):

... if x is None: x = [] # 没有传入参数?
... x.append(1) # 改变新的列表
... print x
...
>>> saver([2]) # 没有使用默认值
[2, 1]
>>> saver() # 这次不会变了
[1]
>>> saver()
[1]

其他常见的编程陷阱
下面列举了其他的一些在这里没法详述的陷阱:
在顶层文件中语句的顺序是有讲究的:因为运行或者加载一个文件会从上到下运行它的语句,所以请确保将你未嵌套的函数调用或者类的调用放在函数或者类的定义之后。
reload不影响用from加载的名字:reload最好和import语句一起使用。如果你使用from语句,记得在reload之后重新运行一遍from,否则你仍然使用之前老的名字。
在多重继承中混合的顺序是有讲究的:这是因为对superclass的搜索是从左到右的,在类定义的头部,在多重superclass中如果出现重复的名字,则以最左边的类名为准。
在try语句中空的except子句可能会比你预想的捕捉到更多的错误。在try语句中空的except子句表示捕捉所有的错误,即便是真正的程序错误,和sys.exit()调用,也会被捕捉到。
从空去听8
2017-08-08 · TA获得超过7439个赞
知道大有可为答主
回答量:6907
采纳率:93%
帮助的人:5579万
展开全部
1.Python异常类

Python是面向对象语言,所以程序抛出的异常也是类。常见的Python异常有以下几个,大家只要大致扫一眼,有个映像,等到编程的时候,相信大家肯定会不只一次跟他们照面(除非你不用Python了)。

异常 描述
NameError 尝试访问一个没有申明的变量
ZeroDivisionError 除数为0
SyntaxError 语法错误
IndexError 索引超出序列范围
KeyError 请求一个不存在的字典关键字
IOError 输入输出错误(比如你要读的文件不存在)
AttributeError 尝试访问未知的对象属性
ValueError 传给函数的参数类型不正确,比如给int()函数传入字符串形

2.捕获异常
Python完整的捕获异常的语句有点像:

复制代码代码如下:

try:
try_suite
except Exception1,Exception2,...,Argument:
exception_suite
...... #other exception block
else:
no_exceptions_detected_suite
finally:
always_execute_suite

额...是不是很复杂?当然,当我们要捕获异常的时候,并不是必须要按照上面那种格式完全写下来,我们可以丢掉else语句,或者finally语句;甚至不要exception语句,而保留finally语句。额,晕了?好吧,下面,我们就来一一说明啦。
2.1.try...except...语句
try_suite不消我说大家也知道,是我们需要进行捕获异常的代码。而except语句是关键,我们try捕获了代码段try_suite里的异常后,将交给except来处理。
try...except语句最简单的形式如下:

复制代码代码如下:

try:
try_suite
except:
exception block

上面except子句不跟任何异常和异常参数,所以无论try捕获了任何异常,都将交给except子句的exception block来处理。如果我们要处理特定的异常,比如说,我们只想处理除零异常,如果其他异常出现,就让其抛出不做处理,该怎么办呢?这个时候,我们就要给except子句传入异常参数啦!那个ExceptionN就是我们要给except子句的异常类(请参考异常类那个表格),表示如果捕获到这类异常,就交给这个except子句来处理。比如:

复制代码代码如下:

try:
try_suite
except Exception:
exception block

举个例子:

复制代码代码如下:

>>> try:
... res = 2/0
... except ZeroDivisionError:
... print "Error:Divisor must not be zero!"
...
Error:Divisor must not be zero!

看,我们真的捕获到了ZeroDivisionError异常!那如果我想捕获并处理多个异常怎么办呢?有两种办法,一种是给一个except子句传入多个异常类参数,另外一种是写多个except子句,每个子句都传入你想要处理的异常类参数。甚至,这两种用法可以混搭呢!下面我就来举个例子。

复制代码代码如下:

try:
floatnum = float(raw_input("Please input a float:"))
intnum = int(floatnum)
print 100/intnum
except ZeroDivisionError:
print "Error:you must input a float num which is large or equal then 1!"
except ValueError:
print "Error:you must input a float num!"

[root@Cherish tmp]# python test.py
Please input a float:fjia
Error:you must input a float num!
[root@Cherish tmp]# python test.py
Please input a float:0.9999
Error:you must input a float num which is large or equal then 1!
[root@Cherish tmp]# python test.py
Please input a float:25.091
4

上面的例子大家一看都懂,就不再解释了。只要大家明白,我们的except可以处理一种异常,多种异常,甚至所有异常就可以了。
大家可能注意到了,我们还没解释except子句后面那个Argument是什么东西?别着急,听我一一道来。这个Argument其实是一个异常类的实例(别告诉我你不知到什么是实例),包含了来自异常代码的诊断信息。也就是说,如果你捕获了一个异常,你就可以通过这个异常类的实例来获取更多的关于这个异常的信息。例如:

复制代码代码如下:

>>> try:
... 1/0
... except ZeroDivisionError,reason:
... pass
...
>>> type(reason)
<type 'exceptions.ZeroDivisionError'>
>>> print reason
integer division or modulo by zero
>>> reason
ZeroDivisionError('integer division or modulo by zero',)
>>> reason.__class__
<type 'exceptions.ZeroDivisionError'>
>>> reason.__class__.__doc__
'Second argument to a division or modulo operation was zero.'
>>> reason.__class__.__name__
'ZeroDivisionError'

上面这个例子,我们捕获了除零异常,但是什么都没做。那个reason就是异常类ZeroDivisionError的实例,通过type就可以看出。
2.2try ... except...else语句
现在我们来说说这个else语句。Python中有很多特殊的else用法,比如用于条件和循环。放到try语句中,其作用其实也差不多:就是当没有检测到异常的时候,则执行else语句。举个例子大家可能更明白些:

复制代码代码如下:

>>> import syslog
>>> try:
... f = open("/root/test.py")
... except IOError,e:
... syslog.syslog(syslog.LOG_ERR,"%s"%e)
... else:
... syslog.syslog(syslog.LOG_INFO,"no exception caught\n")
...
>>> f.close()

2.3 finally子句
finally子句是无论是否检测到异常,都会执行的一段代码。我们可以丢掉except子句和else子句,单独使用try...finally,也可以配合except等使用。
例如2.2的例子,如果出现其他异常,无法捕获,程序异常退出,那么文件 f 就没有被正常关闭。这不是我们所希望看到的结果,但是如果我们把f.close语句放到finally语句中,无论是否有异常,都会正常关闭这个文件,岂不是很 妙

复制代码代码如下:

>>> import syslog
>>> try:
... f = open("/root/test.py")
... except IOError,e:
... syslog.syslog(syslog.LOG_ERR,"%s"%e)
... else:
... syslog.syslog(syslog.LOG_INFO,"no exception caught\n")
... finally:
>>> f.close()

大家看到了没,我们上面那个例子竟然用到了try,except,else,finally这四个子句!:-),是不是很有趣?到现在,你就基本上已经学会了如何在Python中捕获常规异常并处理之。
3.两个特殊的处理异常的简便方法
3.1断言(assert)
什么是断言,先看语法:

复制代码代码如下:

assert expression[,reason]

其中assert是断言的关键字。执行该语句的时候,先判断表达式expression,如果表达式为真,则什么都不做;如果表达式不为真,则抛出异常。reason跟我们之前谈到的异常类的实例一样。不懂?没关系,举例子!最实在!

复制代码代码如下:

>>> assert len('love') == len('like')
>>> assert 1==1
>>> assert 1==2,"1 is not equal 2!"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: 1 is not equal 2!

我们可以看到,如果assert后面的表达式为真,则什么都不做,如果不为真,就会抛出AssertionErro异常,而且我们传进去的字符串会作为异常类的实例的具体信息存在。其实,assert异常也可以被try块捕获:

复制代码代码如下:

>>> try:
... assert 1 == 2 , "1 is not equal 2!"
... except AssertionError,reason:
... print "%s:%s"%(reason.__class__.__name__,reason)
...
AssertionError:1 is not equal 2!
>>> type(reason)
<type 'exceptions.AssertionError'>

3.2.上下文管理(with语句)
如果你使用try,except,finally代码仅仅是为了保证共享资源(如文件,数据)的唯一分配,并在任务结束后释放它,那么你就有福了!这个with语句可以让你从try,except,finally中解放出来!语法如下:

复制代码代码如下:

with context_expr [as var]:
with_suite

是不是不明白?很正常,举个例子来!

复制代码代码如下:

>>> with open('/root/test.py') as f:
... for line in f:
... print line

上面这几行代码干了什么?
(1)打开文件/root/test.py
(2)将文件对象赋值给 f
(3)将文件所有行输出
(4)无论代码中是否出现异常,Python都会为我们关闭这个文件,我们不需要关心这些细节。
这下,是不是明白了,使用with语句来使用这些共享资源,我们不用担心会因为某种原因而没有释放他。但并不是所有的对象都可以使用with语句,只有支持上下文管理协议(context management protocol)的对象才可以,那哪些对象支持该协议呢?如下表:
file
decimal.Context
thread.LockType
threading.Lock
threading.RLock
threading.Condition
threading.Semaphore
threading.BoundedSemaphore
至于什么是上下文管理协议,如果你不只关心怎么用with,以及哪些对象可以使用with,那么我们就不比太关心这个问题:)
4.抛出异常(raise)
如果我们想要在自己编写的程序中主动抛出异常,该怎么办呢?raise语句可以帮助我们达到目的。其基本语法如下:

复制代码代码如下:

raise [SomeException [, args [,traceback]]

第一个参数,SomeException必须是一个异常类,或异常类的实例
第二个参数是传递给SomeException的参数,必须是一个元组。这个参数用来传递关于这个异常的有用信息。
第三个参数traceback很少用,主要是用来提供一个跟中记录对象(traceback)
下面我们就来举几个例子。

复制代码代码如下:

>>> raise NameError
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError
>>> raise NameError() #异常类的实例
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError
>>> raise NameError,("There is a name error","in test.py")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
>>> raise NameError("There is a name error","in test.py") #注意跟上面一个例子的区别
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: ('There is a name error', 'in test.py')
>>> raise NameError,NameError("There is a name error","in test.py") #注意跟上面一个例子的区别
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: ('There is a name error', 'in test.py')

其实,我们最常用的还是,只传入第一个参数用来指出异常类型,最多再传入一个元组,用来给出说明信息。如上面第三个例子。
5.异常和sys模块
另一种获取异常信息的途径是通过sys模块中的exc_info()函数。该函数回返回一个三元组:(异常类,异常类的实例,跟中记录对象)

复制代码代码如下:

>>> try:
... 1/0
... except:
... import sys
... tuple = sys.exc_info()
...
>>> print tuple
(<type 'exceptions.ZeroDivisionError'>, ZeroDivisionError('integer division or modulo by zero',), <traceback object at 0x7f538a318b48>)
>>> for i in tuple:
... print i
...
<type 'exceptions.ZeroDivisionError'> #异常类
integer division or modulo by zero #异常类的实例
<traceback object at 0x7f538a318b48> #跟踪记录对象
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
小猿圈IT教育
2019-04-23 · 超过11用户采纳过TA的回答
知道答主
回答量:76
采纳率:57%
帮助的人:9.6万
展开全部
到底是什么问题呢?需要你把具体问题展示出来,我这边才能给你解答的哦。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式