python自学第32天 python之小白太玄经 2019.12.24

6.1.1作为脚本来执行模块

运行模块中的代码
在这里插入图片描述
模块中的代码会被执行,就像导入它一样,不过此时__name__被设置为“main",相当于在模块后加入如下代码:
在这里插入图片描述
让此文件像作为模块导入时一样作为脚本执行,此代码只有在模块作为main文件执行时才被调用:
在这里插入图片描述
模块被导入,不会执行这段代码
在这里插入图片描述

6.1.2模块的搜索路径

导入一个叫 spam的模块时,解释器会先在当前目录中搜索名为spam.py的文件。
如果没有找到的话,接着会到sys.path变量中给出的目录列表中查找。
sys.path变量的初始值来自如下:

输入脚本的目录(当前目录)。
环境变量PYTHONNPATH表示的目录列表中搜索
(这和shell变量path具有一样的语法,即一系列目录名的列表)。
python默认安装路径中搜索。

6.1.3”编译的“python文件

为了加快加载模块的速度
python会在__pycache__目录下以module.version.pyc名字缓存每个模块编译后的版本,(这里的版本编制了编译后的文件的格式)

6.2.标准模块

python带有一个标准的模块库,并发布有独立的文档。名为python库参考手册。(库参考手册)

有一些模块内置于解释器之中,这些操作的访问接口不是语言内核的一部分,但是已经内置于解释器了。

6.3dir()函数

内置函数dir()用于按模块名搜索模块定义,它返回一个字符串类型的列表:
在这里插入图片描述
无参数调用时,dir()函数返回当前定义的命名:

在这里插入图片描述
该列表 列出了所有类型的名称:变量,模块,函数,等

dir()不会列出内置函数和变量名。如果你想列出这些内容,它们在标准模块builtins中定义:

在这里插入图片描述

6.4.包

包通常是使用用”圆点模块名“的结构化模块命名空间。
例如,名为A.B的模块表示了名为A的包中名为B的子模块。
正如同用模块来保存不同的模块架构,可以避免全局变量之间的相互冲突,
使用圆点模块名保存像Numpy或python lmaging Library之类的不同类库架构可以避免模块之间的命名冲突。

假设你现在想要设计一个模块集(一个”包“)来统一处理声音文件和声音数据。存在几种不同的声音格式(通常由它们的扩展名来标识,例如:。wav,.aiff,.au),于是,为了在不同类型的文件格式之间转换,需要维护一个不断增长的包集合。
可能还想要对声音数据做很多不同的操作(如混音,添加回声,应用平衡功能,创建一个人造效果),所以你要加入一个无限流模块来执行这些操作。你的包可能会是这个样子
示例
在这里插入图片描述

当导入这个包时,python通过sys。path搜索路径查找到这个包的子目录。

为了让python将目录当做内容包,目录中必须包含__init__.py文件。这是为了避免一个含有烂俗名字的目录无意中隐藏了稍后在模块搜索路径中出现的有效模块,比如string。
最简单的情况下,只需要一个空的__inti__.py文件即可。当然它也可以执行包的初始化代码,或者定义稍后介绍的__all__变量。

用户可以每次只导入包里的特定模块,例如
在这里插入图片描述
这样就导入了 sound.effects.echo子模块。它必须通过完整的名称来引用:
在这里插入图片描述
导入包时有一个可以选择的方式:

在这里插入图片描述
这样就加载了echo子模块,并且使得它在没有包前缀的情况下也可以使用,所以它可以如下方式调用:
在这里插入图片描述

还有另一种变体用于直接导入函数或变量:

在这里插入图片描述
这样就又一次加载了echo子模块,但这样就可以直接调用它的echofilter()函数:
在这里插入图片描述
需要注意的是,使用from package import item 方式导入包时,这个子项(item)即可以是包中的一个子模块(或一个子包),也可以是包中定义的其它命名,像函数,类或变量。import语句首先核对是否包中有这个子项,如果没有,它假定这是一个模块,并尝试加载它,如果没有找到它,会引发一个lmportError异常。

相反,使用类似 import item.subitem,subsubitem 这样的语法时,这些子项必须是包,最后的子项可以是包或模块,但不能是前面子项中定义的类。函数或变量。

6.4.1.从*导入包

当用户写下 from sound.effects import *时,会发生??
理想中,希望找到包中的所有子模块,然后导入它们。
这可能花掉很长时间,并且出现之外的边界效应,导出了希望只能显示导入的包。

对于包的作者来说唯一的解决方案就是给提供一个明确的包索引。
import语句按如下条件进行转换:
执行from package import * 时,如果包中的__init__.py代码定义了一个名为__all__的列表,就会按照列表中的给出的模块名进行导入。

在这里插入图片描述
这就意味着 from sound.effects import *语句会从sound包中导入以上三个已命名的子模块。

7.输入和输出

一个程序可以有几种输出方式:以人类可读的方式打印数据,或者写入要给文件供以后使用。

7.1.1格式化输出

有两种大相近庭的输出值方法
表达式语句和print()函数(第三种访求是使用文件对象的write()方法
标准文件输出可以参考sys.stdout)

对输出做更多的格式控制。而不是简单的打印使用空格分隔的值。
两种方法:
第一种:由自己处理整个字符串,通过使用字符串切割和连接操作可以创建任何你想要的输出形式。string类型包含一些将字符串填充到指定列宽度的有用操作,随后就会讨论这些。
第二种:使用str.format()方法。

标准模块string包括了一些操作,将字符串填充入给定列时,这些操作很有用。
第二种方法是使用Template方法。

当然,还有一个问题,如何将值转化为字符串?
python有办法将任意值转化为字符串:将它传入repr()或str()函数。

函数str()用于将值转化为适于人阅读的形式,而repr()转化为供解释器读取的形式(如果没有等价的语法,则会发生SyntaxError异常)
某对象没有适于人阅读的解释形式的话,str()会返回与repr()等同的值。
很多类型,诸如数值或链表,字典这样的结构,针对各函数都有着统一的解读方式,字符串和浮点数。
示例:
在这里插入图片描述
有两种方式可以写平方和立方表:

在这里插入图片描述
在这里插入图片描述
注意第一个例子,print()在每列之间加了一个空格,总是在参数间加入空格。)

以上是一个str.rjust()方法的演示,它把字符串输出到一列,并通过向左侧填充空格来使其右对齐。类似的方法还有str.ljust()和str/center().这些函数只是输出新的字符串,并不改变什么。如果输出的字符串太长,它们也不会截断它。而是原样输出。
这会使你的输出格式变得混乱,不过总强过另一种选择(截断字符串),
因为那样会产生错误的输出值(如果你确实需要截断它,可以使用切割操作,例如 x.ljust(n)[:n])

还有另一种方法,str.zfill()它用于向数值的字符串表达左侧填充0.
该函数可以正确理解正负号:
在这里插入图片描述
方法str.format()的基本用法如下:

在这里插入图片描述
大括号和其中的字符会被替换成传入str.format()的参数。大括号中的数值指明使用传入str.format()方法的对象中的哪一个:

在这里插入图片描述
如果在str.format()调用时使用关键字参数,可以通过参数名来引用值:

在这里插入图片描述
位置参数和关键字参数可以随意组合:
在这里插入图片描述
'!a’应用 ascii()
'!s’应用于str()
'!r’应用于repr()
可以在格式化之前转换值:
在这里插入图片描述
字段名后允许可选的’:‘和格式指令。这允许对值的格式化加以更深的控制,下面将Pi转为三位精度。
在这里插入图片描述
在字段后的’:‘后面加一个整数会限定该字段的最小宽度,这在美化表格时很有用:
在这里插入图片描述

如果有个很长的格式化字符串,不想分割它。如果你可以用命名来引用被格式化的变量而不是位置就好了。有个简单的方法,可以传入一个字典,用中括号(’[]'访问它的键:

在这里插入图片描述

也可以用‘**’标志将这个字典以关键字参数的方式传入:
在这里插入图片描述
这种方式与新的内置函数vars()组合使用非常有效。该函数返回包含所有局部变量的字典。

7.1.1.旧式的字符串格式化

操作符%也可以用于字符串格式化。
它以类似sprintf()-style的方式解析左参数,将右参数应用于此,得到格式化操作生成的字符串,例如:

在这里插入图片描述

7.2…文件读写

函数open() 返回文件对象,通常的用法需要两个参数open(filename, mode).

f = open(‘workfile’, ‘w’)

第一个参数是一个含有文件名的字符串。
第二个参数也是一个字符串。含有描述如何使用该文件的几个字符。

mode为‘r’时表示只是读取文件
’w’表示只是写入文件(已经存在的同名文件将被删除)
‘a’表示打开打开文件进行追加,写入到文件中的任何数据将自动添加到末尾。
’r+‘表示打开文件进行读取和写入。
mode参数是可选的,默认为‘r’
通常,文件以文本打开,这意味着,你从文件读出和向文件写入的字符串会被特定的编码方式(默认是UTF-8)编码。模式后面的’b’以二进制模式打开文件:数据会以字节对象的形式读出和写入。这种模式应该用于所有不包括文本的文件。

在文本模式下,读取时默认会将平台有关的行结束符(unix时\n,windows是\r\n)转换为\n。在文本模式下写入时,默认会将出现的\n转换成平台有关的行结束符。

这种暗地里修改对ASCLL文本文件没有问题,但会损坏JPEG或EXE这样的二进制文件中的数据。使用二进制模式读写此类文件时要特别小心。

7.2.1.文件对象方法

本节示例都默认文件对象f已经创建。
要读取文件内容,需要调用f.read(size),该方法读取若干数量的数据并以字符串形式返回其内容,size是可选的数值,指定字符串长度。

如果没有指定size或者指定为负数,就会读取并返回整个文件。当文件大小为当前机器内存两倍时,就会产生问题。反之,会尽可能按比较大的size读取和返回数据。如果到了文件末尾,f.read()会返回一个空字符串‘ ’。

在这里插入图片描述
f.readline()从文件中读取单独一行,字符串结尾会自动加上一个换行符(\n),只有当文件最后一行没有以换行符结尾时,这一操作才会被忽略。
这样返回值就不会有混淆,如果f.readline()返回一个空字符串,那就表示到达了文件末尾,如果是一个空行,就会描述为’\n’,一个只包含换行符的字符串:

在这里插入图片描述
你可以循环遍历文件对象来读取文件中的每一行。这是一种内存高效,快速,并且代码简介方式:

在这里插入图片描述
如果你想把文件中的所有行读到一个列表中,你也可以使用list(f)或者f.readlines().
f.write(string)方法将string的内容写入文件,并返回写入字符的长度:
在这里插入图片描述
想要写入其他非字符串内容,首先要将它转换为字符串:

在这里插入图片描述

f.tell()返回一个整数,代表文件对象在文件中的指针位置,该数值计量了自文件开头到指针处的比特数。需要改变文件对象指针话话,使用f.seek(offset,from_what).指针在该操作中从指定的引用位置移动offset比特,引用位置由from_what参数指定。from_what值为0表示自文件起始处开始,1表示自当前文件指针位置开始,2表示自文件末尾开始。from_what可以忽略,其默认值为零,此时从文件头开始:
在这里插入图片描述
在文本文件中(没有以b模式打开,只允许从文件头开始寻找(有个例外是用seek(0,2)寻找文件的最末尾处)而且合法的偏移值只能是f.tell()返回的值或者是零。
其他任何偏移值都会产生未定义的行为。

当你使用完一个文件时,调用f.close()方法就可以关闭它并释放其占用的所有系统资源。在调用f.close()方法后,试图再次使用文件对象将会自动失败。

在这里插入图片描述
用关键字with处理文件对象是个好习惯。它的先进之处在于文件用完后会自动关闭,就算发生异常也没关系,他是try-finally块的简写:

在这里插入图片描述

8.错误和异常

8.1.语法错误

SyntaxError: invalid syntax
语法分析器指出错误行,并且在检测到错误的位置前面显示一个小箭头。错误是由箭头前面的标记引起的(或者至少是这么检测的);

8.2异常

即时一条语句或表达式在语法是是正确的,当试图执行它时也可能会引发错误。
运行期检测到的错误称为异常。并且程序不会无条件的崩溃。

错误信息的最后一行指出发生了什么错误。
ZeroDivisionError 零除错误
NameError 命名错误
TypeError 类型错误

8.3.异常处理

通过编程处理异常是可行的。
示例:会一直要求用户输入,直到输入一个合法的整数为止,但允许用户中断这个程序(使用Control-c或系统支持的任何方法)。注意,用户产生的中断会引发一个Keyboardlnterrupt异常。

在这里插入图片描述
try语句按如下方式工作。

首先,执行try子句(在try和except关键字之间的部分)
如果没发生异常发生,except子句在try语句执行完毕后就忽略了。
如果在try子句执行过程中发生了异常,那么该子句其余的部分就会被忽略。
如果异常匹配于except关键字后面指定的异常类型,就执行对应的except子句。然后继续执行try语句之后的代码。
如果发生了一个异常,在except子句中没有与之匹配的分支,它就会传递到上一级try语句中。
如果最终仍找不到对应的处理语句,它就成为一个未处理异常,终止程序运行,显示提示信息。

一个try语句可能包含多个except子句,分别指定处理不同的异常。至多只会有一个分支被执行。异常处理程序只会处理对应的try子句中发生的异常,在同一个try语句中,其他子句中发生的异常则不作处理。一个except子句可以在括号中列出多个异常的名字,例如:
在这里插入图片描述
最后一个except子句可以省略异常名称,以作为通配符使用。你需要慎用此法,因为它会轻易隐藏一个实际的程序错误!可以使用这种方法打印一条错误信息,然后重新抛出异常(允许调用者处理整个异常):
在这里插入图片描述
try…except 语句可以带有一个else 子句,该子句只能出现在所有except子句之后。
当try语句没有抛出异常时,需要执行一些代码,可以使用这个子句。例如:
在这里插入图片描述
使用else子句比在try子句中附加代码要好,因为这样可以避免try…except 意外的截获本来不属于它们保护的那么代码抛出的异常。

发生异常时,可能会有一个附属值,作为异常的参数存在。这个参数是否存在,是什么类型,依赖于异常的类型。

在异常名(列表)之后,也可以为except子句指定一个变量。这个变量绑定于一个异常实例,它存储在instance.args的参数中。为了方便起见,异常实例定义了_str_(),这样就可以直接访问过打印参数而不必引用.args。这种做法不受鼓励。相反,更好的做法是给异常传递一个参数(如果要传递多个参数,可以传递一个元组),把它绑定到message属性。一旦异常发生,它会在抛出前绑定所有指定的属性。

在这里插入图片描述
对于那些未处理的异常,如果一个它们带有参数,那么就会被作为异常信息的最后部分(’详情‘)打印出来。

异常处理器不仅仅处理那些在try子句中立刻发生的异常,也会处理那些try子句中调用的函数内部发生的异常。例如:

在这里插入图片描述

今日学习结束,已学习8.4章,剩余8章,已学习71页,剩余50页。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值