python补充.docx

上传人:b****6 文档编号:6940624 上传时间:2023-01-12 格式:DOCX 页数:19 大小:30.49KB
下载 相关 举报
python补充.docx_第1页
第1页 / 共19页
python补充.docx_第2页
第2页 / 共19页
python补充.docx_第3页
第3页 / 共19页
python补充.docx_第4页
第4页 / 共19页
python补充.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

python补充.docx

《python补充.docx》由会员分享,可在线阅读,更多相关《python补充.docx(19页珍藏版)》请在冰豆网上搜索。

python补充.docx

python补充

标准异常:

∙Exception 是所有异常的基类.强烈建议(但不是必须)自定义的异常异常也继承这个类.

∙SystemExit(Exception) 由 sys.exit 函数引发.如果它在最顶层没有被 try-except 语句捕获,那么解释器将直接关闭而不会显示任何跟踪返回信息.

∙StandardError(Exception) 是所有内建异常的基类(除 SystemExit 外).

∙KeyboardInterrupt(StandardError) 在用户按下Control-C(或其他打断按键)后被引发.如果它可能会在你使用"捕获所有"的 try-except 语句时导致奇怪的问题.

∙ImportError(StandardError) 在Python导入模块失败时被引发.

∙EnvironmentError 作为所有解释器环境引发异常的基类.(也就是说,这些异常一般不是由于程序bug引起).

∙IOError(EnvironmentError) 用于标记I/O相关错误.

∙OSError(EnvironmentError) 用于标记 os 模块引起的错误.

∙WindowsError(OSError) 用于标记 os 模块中Windows相关错误.

∙NameError(StandardError) 在Python查找全局或局部名称失败时被引发.

∙UnboundLocalError(NameError) ,当一个局部变量还没有赋值就被使用时,会引发这个异常.这个异常只有在2.0及之后的版本有;早期版本只会引发一个普通的 NameError .

∙AttributeError(StandardError) ,当Python寻找(或赋值)给一个实例属性,方法,模块功能或其它有效的命名失败时,会引发这个异常.

∙SyntaxError(StandardError) ,当解释器在编译时遇到语法错误,这个异常就被引发.

∙(2.0及以后版本) IndentationError(SyntaxError) 在遇到非法的缩进时被引发.该异常只用于2.0及以后版本,之前版本会引发一个 SyntaxError 异常.

∙(2.0及以后版本) TabError(IndentationError) ,当使用 -tt 选项检查不一致缩进时有可能被引发.该异常只用于2.0及以后版本,之前版本会引发一个SyntaxError 异常.

∙TypeError(StandardError) ,当给定类型的对象不支持一个操作时被引发.

∙AssertionError(StandardError) 在 assert 语句失败时被引发(即表达式为false时).

∙LookupError(StandardError) 作为序列或字典没有包含给定索引或键时所引发异常的基类.

∙IndexError(LookupError) ,当序列对象使用给定索引数索引失败时(不存在索引对应对象)引发该异常.

∙KeyError(LookupError) 当字典对象使用给定索引索引失败时(不存在索引对应对象)引发该异常.

∙ArithmeticError(StandardError) 作为数学计算相关异常的基类.

∙OverflowError(ArithmeticError) 在操作溢出时被引发(例如当一个整数太大,导致不能符合给定类型).

∙ZeroDivisionError(ArithmeticError) ,当你尝试用0除某个数时被引发.

∙FloatingPointError(ArithmeticError) ,当浮点数操作失败时被引发.

∙ValueError(StandardError) ,当一个参数类型正确但值不合法时被引发.

∙(2.0及以后版本) UnicodeError(ValueError) ,Unicode字符串类型相关异常.只使用在2.0及以后版本.

∙RuntimeError(StandardError) ,当出现运行时问题时引发,包括在限制模式下尝试访问外部内容,未知的硬件问题等等.

∙NotImplementedError(RuntimeError) ,用于标记未实现的函数,或无效的方法.

∙SystemError(StandardError) ,解释器内部错误.该异常值会包含更多的细节(经常会是一些深层次的东西,比如"eval_code2:

NULLglobals").这本书的作者编了5年程序都没见过这个错误.(想必是没有用 raiseSystemError).

∙MemoryError(StandardError) ,当解释器耗尽内存时会引发该异常.注意只有在底层内存分配抱怨时这个异常才会发生;如果是在你的旧机器上,这个异常发生之前系统会陷入混乱的内存交换中

编码转换

python有strobject和unicodeobject两种字符串,都可以存放字符的字节编码,但是他们是不同的type,这一点很重要,也是为什么会有encode和decode。

encode和decode在pyhton 中的意义可表示为

                                                                 encode

                                              unicode------------------------->str

                                             unicode<--------------------------str

                                                                 decode

几种常用法:

str_string.decode('codec')是把str_string转换为unicode_string,codec是源str_string的编码方式

unicode_string.encode('codec')是把unicode_string转换为str_string,codec是目标str_string的编码方式

str_string.decode('from_codec').encode('to_codec')可实现不同编码的str_string之间的转换

比如:

>>> t='长城'

>>> t

'\xb3\xa4\xb3\xc7'

>>> t.decode('gb2312').encode('utf-8')

'\xe9\x95\xbf\xe5\x9f\x8e'

str_string.encode('codec')是先调用系统的缺省codec去把str_string转换为unicode_string,然后用encode的参数codec去转换为最终的str_string.相当于str_string.decode('sys_codec').encode('codec')。

unicode_string.decode('codec')基本没有意义,unicode在python里只用一种unicode编码,UTF16或者UTF32(编译python时就已经确定),没有编码转换的需要。

 

注:

缺省codec在site-packages下的sitecustomize.py文件中指定,比如

import sys

sys.setdefaultencoding('utf-8')

5.2案例研究:

街道地址

下面一系列的示例的灵感来自于现实生活中我几年前每天的工作。

我需要把一些街道地址导入一个新的系统,在这之前我要从一个遗留的老系统中清理和标准化这些街道地址。

下面这个例子展示我怎么解决这个问题。

>>>s='100NORTHMAINROAD'

>>>s.replace('ROAD','RD.')①

'100NORTHMAINRD.'

>>>s='100NORTHBROADROAD'

>>>s.replace('ROAD','RD.')②

'100NORTHBRD.RD.'

>>>s[:

-4]+s[-4:

].replace('ROAD','RD.')③

'100NORTHBROADRD.'

>>>importre④

>>>re.sub('ROAD$','RD.',s)⑤

'100NORTHBROADRD.'

1.我的目的是要标准化街道的格式。

而‘ROAD’总是在.RD的前面。

刚开始我以为只需要简单的使用string的replace()方法就可以。

所有的数据都是大写的,因此不会出现大小写不匹配的问题。

而查找的字符串‘ROAD’也是一个常量。

在这个简单的例子中s.replace()可以很好的工作。

2.事实上,不幸的是,我很快发现一个问题,在一些地址中‘ROAD’出现了两次,一个是前面的街道名里带了‘ROAD’,一个是‘ROAD’本身。

repalce()发现了两个就把他们都给替换掉了。

这意味着,我的地址错了。

3.为了解决地址中出现超过一个‘ROAD’子字符串的问题,你可能会这么考虑:

只在地址的最后四个字符中查找和替换‘‘ROAD’(s[-4:

])。

然后把剩下的字符串独立开来处理(s[:

-4])。

这个方法很笨拙。

比如,这个方法会依赖于你要替换的字符串长度(如果你用‘.ST’来替换‘STREET’,就需要在s[-6:

]中查找‘STREET’,然后再取s[:

-6]。

你难道还想半年后回来继续修改BUG?

反正我是不想。

4.是时候转换到正则表达式了。

在python中,所有的正则表达式相关功能都包含在re模块中。

5.注意第一个参数‘ROAD$’,这是一个匹配‘ROAD’仅仅出现在字符串结尾的正则表达式。

$表示“字符串结尾”。

(还有一个相应的表示“字符串开头”的字符^)。

正则表达式模块的re.sub()函数可以做字符串替换,它在字符串s中用正则表达式‘ROAD$’来搜索并替换成‘RD.’。

它只会匹配字符串结尾的‘ROAD’,而不会匹配到‘BROAD’中的‘ROAD’,因为这种情况它在字符串的中间。

^匹配字符串开始.$匹配字符串结尾

继续我的处理街道地址的故事。

我很快发现,在之前的例子中,匹配地址结尾的‘ROAD’不够好。

因为并不是所有的地址结尾都有它。

一些地址简单的用一个街道名结尾。

大部分的情况下不会有问题,但如果街道的名字就叫‘BROAD’,这个时候,正则表达式会匹配到‘BROAD’的最后4个字符,这并不是我想要的。

>>>s='100BROAD'

>>>re.sub('ROAD$','RD.',s)

'100BRD.'

>>>re.sub('\\bROAD$','RD.',s)①

'100BROAD'

>>>re.sub(r'\bROAD$','RD.',s)②

'100BROAD'

>>>s='100BROADROADAPT.3'

>>>re.sub(r'\bROAD$','RD.',s)③

'100BROADROADAPT.3'

>>>re.sub(r'\bROAD\b','RD.',s)④

'100BROADRD.APT3'

1.我真正想要的‘ROAD’,必须是匹配到字符串结尾,并且是独立的词(他不能是某个比较长的词的一部分)。

为了在正则表达式中表达这个独立的词,你可以使用‘\b’。

它的意思是“在右边必须有一个分隔符”。

在python中,比较复杂的是‘\’字符必须被转义,这有的时候会导致‘\’字符传染(想想可能还要对\字符做转义的情况)。

这也是为什么perl中的正则表达式比python的简单的原因之一。

另一方面,perl会在正则表达式中混合其他非正则表达式的语法,如果出现了bug,那么很难区分这个bug是在正则表达式中,还是在其他的语法部分。

2.为了解决‘\’字符传染的问题,可以使用原始字符串。

这只需要在字符串的前面添加一个字符‘r’。

它告诉python,字符串中没有任何字符需要转义。

‘\t’是一个制表符,但r‘\t’只是一个字符‘\’紧跟着一个字符t。

我建议在处理正则表达式的时候总是使用原始字符串。

否则,会因为理解正则表达式而消耗大量时间(本身正则表达式就已经够让人困惑的了)。

3.哎,不幸的是,我发现了更多的地方与我的逻辑背道而驰。

街道地址包含了独立的单词‘ROAD’,但并不是在字符串尾,因为街道后面还有个单元号。

因为'ROAD'并不是最靠后,就不能匹配,因此re.sub()最后没有做任何的替换,只是返回了一个原始的字符串,这并不是你想要的。

4.为了解决这个问题,我删除了正则表达式尾部的$,然后添加了一个\b。

现在这个正则表达式的意思是“在字符串的任意位置匹配独立的‘ROAD’单词”不管是在字符串的结束还是开始,或者中间的任意一个位置。

案例研究:

罗马数字

你肯定见过罗马数字,即使你不认识他们。

你可能在版权信息、老电影、电视、大学或者图书馆的题词墙看到(用CopyrightMCMXLVI”表示版权信息,而不是用“Copyright1946”),你也可能在大纲或者目录参考中看到他们。

这种系统的数字表达方式可以追溯到罗马帝国(因此而得名)。

在罗马数字中,有七个不同的数字可以以不同的方式结合起来表示其他数字。

∙I=1

∙V=5

∙X=10

∙L=50

∙C=100

∙D=500

∙M=1000

下面是几个通常的规则来构成罗马数字:

∙大部分时候用字符相叠加来表示数字。

I是1,II是2,III是3。

VI是6(挨个看来,是“5和1”的组合),VII是7,VIII是8。

∙含有10的字符(I,X,C和M)最多可以重复出现三个。

为了表示4,必须用同一位数的下一个更大的数字5来减去一。

不能用IIII来表示4,而应该是IV(意思是比5小1)。

40写做XL(比50小10),41写做XLI,42写做XLII,43写做XLIII,44写做XLIV(比50小10并且比5小1)。

∙有些时候表示方法恰恰相反。

为了表示一个中间的数字,需要从一个最终的值来减。

比如:

9需要从10来减:

8是VIII,但9确是IX(比10小1),并不是VIII(I字符不能重复4次)。

90是XC,900是CM。

∙表示5的字符不能在一个数字中重复出现。

10只能用X表示,不能用VV表示。

100只能用C表示,而不是LL。

∙罗马数字是从左到右来计算,因此字符的顺序非常重要。

DC表示600,而CD完全是另一个数字400(比500小100)。

CI是101,IC不是一个罗马数字(因为你不能从100减1,你只能写成XCIX,表示比100小10,且比10小1)。

检查千位数

怎么验证一个字符串是否是一个合法的罗马数字呢?

我们可以每次取一个字符来处理。

因为罗马数字总是从高位到低位来书写。

我们从最高位的千位开始。

表示1000或者更高的位数值,方法是用一系列的M来重复表示。

>>>importre

>>>pattern='^M?

M?

M?

$'①

>>>re.search(pattern,'M')②

<_sre.SRE_Matchobjectat0106FB58>

>>>re.search(pattern,'MM')③

<_sre.SRE_Matchobjectat0106C290>

>>>re.search(pattern,'MMM')④

<_sre.SRE_Matchobjectat0106AA38>

>>>re.search(pattern,'MMMM')⑤

>>>re.search(pattern,'')⑥

<_sre.SRE_Matchobjectat0106F4A8>

1.这个模式有三部分。

^表示必须从字符串开头匹配。

如果没有指定^,这个模式将在任意位置匹配M,这个可能并不是你想要的。

你需要确认是否要匹配字符串开始的M,还是匹配单个M字符。

因为它重复了三次,你要在一行中的任意位置匹配0到3次的M字符。

$匹配字符串结束。

当它和匹配字符串开始的^一起使用,表示匹配整个字符串。

没有任何一个字符可在M的前面或者后面。

2.re模块最基本的方法是search()函数。

它使用正则表达式来匹配字符串(M)。

如果成功匹配,search()返回一个匹配对象。

匹配对象中有很多的方法来描述这个匹配结果信息。

如果没有匹配到,search()返回None。

你只需要关注search()函数的返回值就可以知道是否匹配成功。

‘M’被正则表达式匹配到了。

原因是正则表达式中的第一个可选的M匹配成功,第二个和第三个被忽略掉了。

3.‘MM’匹配成功。

因为正则表达式中的第一个和第二个可选的M匹配到,第三个被忽略。

4.‘MMM’匹配成功。

因为正则表达式中的所有三个M都匹配到。

5.‘MMMM’匹配失败。

正则表达式中所有三个M都匹配到,接着正则表达式试图匹配字符串结束,这个时候失败了。

因此search()函数返回None。

6.有趣的是,空字符串也能匹配成功,因为正则表达式中的所有M都是可选的。

检查百位数

?

表示匹配是可选的

百位的匹配比千位复杂。

根据值的不同,会有不同的表达方式。

∙100=C

∙200=CC

∙300=CCC

∙400=CD

∙500=D

∙600=DC

∙700=DCC

∙800=DCCC

∙900=CM

因此会有四种可能的匹配模式:

∙CM

∙CD

∙可能有0到3个字符C(0个表示千位为0)。

∙D紧跟在0到3个字符C的后面。

这两个模式还可以组合起来表示:

∙一个可选的D,后面跟着0到3个字符C。

下面的例子展示了怎样在罗马数字中验证百位。

>>>importre

>>>pattern='^M?

M?

M?

(CM|CD|D?

C?

C?

C?

)$'①

>>>re.search(pattern,'MCM')②

<_sre.SRE_Matchobjectat01070390>

>>>re.search(pattern,'MD')③

<_sre.SRE_Matchobjectat01073A50>

>>>re.search(pattern,'MMMCCC')④

<_sre.SRE_Matchobjectat010748A8>

>>>re.search(pattern,'MCMC')⑤

>>>re.search(pattern,'')⑥

<_sre.SRE_Matchobjectat01071D98>

1.这个正则表达式的写法从上面千位的匹配方法接着往后写。

检查字符串开始(^),然后是千位,后面才是新的部分。

这里用圆括号定义了三个不同的匹配模式,他们是用竖线分隔的:

CM,CD和D?

C?

C?

C?

(这表示是一个可选的D,以及紧跟的0到3个可选的字符C)。

正则表达式按从左到右的顺序依次匹配,如果第一个CM匹配成功,用竖线分隔这几个中的后面其他的都会被忽略。

2.‘MCM’匹配成功。

因为第一个M匹配到,第二个和第三个M被忽略。

后面的CM匹配到(因此后面的CD和D?

C?

C?

C?

根本就不被考虑匹配了)。

MCM在罗马数字中表示1900。

3.‘MD’匹配成功。

因为第一个M匹配到,第二个和第三个M被忽略。

然后D?

C?

C?

C?

匹配到D(后面的三个C都是可选匹配的,都被忽略掉)。

MD在罗马数字中表示1500。

4.‘MMMCCC’匹配成功。

因为前面三个M都匹配到。

后面的D?

C?

C?

C?

匹配CCC(D是可选的,它被忽略了)。

MMMCCC在罗马数字中表示3300。

5.‘MCMC’匹配失败。

第一个M被匹配,第二个和第三个M被忽略,然后CM匹配成功。

紧接着$试图匹配字符串结束,但后面是C,匹配失败。

C也不能被D?

C?

C?

C?

匹配到,因为CM和它只能匹配其中一个,而CM已经匹配过了。

6.有趣的是,空字符串仍然可以匹配成功。

因为所有的M都是可选的,都可以被忽略。

并且后面的D?

C?

C?

C?

也是这种情况。

哈哈,看看正则表达式如此快速的处理了这些令人厌恶的东西。

你已经可以找到千位数和百位数了!

后面的十位和个位的处理和千位、百位的处理是一样的。

但我们可以看看怎么用另一种方式来写这个正则表达式。

使用语法{n,m}

{1,4}匹配1到4个前面的模式

在上一节中,你处理过同样的字符可以重复0到3次的情况。

实际上,还有另一种正则表达式的书写方式可以表达同样的意思,而且这种表达方式更具有可读性。

首先看看我们在前面例子中使用的方法。

>>>importre

>>>pattern='^M?

M?

M?

$'

>>>re.search(pattern,'M')①

<_sre.SRE_Matchobjectat0x008EE090>

>>>pattern='^M?

M?

M?

$'

>>>re.search(pattern,'MM')②

<_sre.SRE_Matchobjectat0x008EEB48>

>>>pattern='^M?

M?

M?

$'

>>>re.search(pattern,'MMM')③

<_sre.SRE_Matchobjectat0x008EE090>

>>>re.search(pattern,'MMMM')④

>>>

1.正则表达式匹配字符串开始,然后是第一个可选的字符M,但没有第二个和第三个M(没问题!

因为他们是可选的),接着是字符串结尾。

2.正则表达式匹配字符串开始,然后是第一个和第二个M,第三个被忽略(因为它是可选的),最后匹配字符串结尾。

3.正则表达式匹配字符串开始,然后是三个M,接着是字符串结尾。

4.正则表达式匹配字符串开始,然后是三个M,但匹配字符串结尾失败(因为后面还有个M)。

因此,这次匹配返回None。

>>>pattern='^M{0,3}$'①

>>>re.search(pattern,'M')②

<_sre.SRE_Matchobjectat0x008EEB48>

>>>re.search(pattern,'MM')③

<_sre.SRE_Matchobjectat0x008EE090>

>>>re.search(pattern,'MMM')④

<_sre.SRE_Matchobjectat0x008EEDA8>

>>>re.search(pattern,'MMMM')⑤

>>>

1.这个正则表达式的意思是“匹配字符串开始,然后是任意的0到3个M字符,再是字符串结尾”。

0和3的位置可以写任意的数字。

如果你想表示可以匹配的最小次数为1次,最多为3次M字符,可以写成M{1,3}。

2.匹配字符串开始,然后匹配了1次M,这在0到3的范围内,接着是字符串结尾。

3.匹配字符串开始,然后

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 广告传媒

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1