元组,文件与其他核心类型
元组
元组是:
任意对象的有序集合
与字符串和列表类似,元组是一个教育为主的有序对象集合(其内容维持从左到右的顺序),与列表类似,它们是可以嵌进任何类型的对象
通过偏移量存数据
同字符串,列表一样,元组中的元素通过偏移量(而不是键)来访问,它们支持所有基于偏移量的操作,例如索引和分片
属于不可变序列
与字符串和列表一样,元组是序列,它们支持许多同样的操作,然而,与字符串相同,元组是不可变的,也就是说元组不支持使用于链表的人格原位置修改操作
固定长度,多样性,任意嵌套
因为元组是不可变的,如果不创建一个新的副本,就不能够增长或缩短元组。另一方面,预祝可以包含其他的符合对象(如列表,字典和其他元组等),因此支持任意嵌套
对象引用的数组
与列表类型,元组应被看做对象引用的数组。元组存储了指向其他对象的存取点(引用),而且对元组进行索引操作的速度比较快
常见元组字面量和运算
() 空元组
T = (0,) 单个元素的元组(非表达式)
T = (0,'Ni',1.2,3) 四个元素的元组
T = 0,'Ni',1.2,3 另一种四个元素的元组(与上一行相同)
T = ('YB',('ASDW','QWE') 嵌套元组
T = tuple('asdw') 一个可迭代对象的元素组成的元组
T[i] 索引
T[i][j] 索引的索引
T[i:j] 分片
len(T) 长度
T1 + T2 拼接
T * 3 重复
for x in T:print(x) 迭代
'asdw' in T 成员关系测试
T.index('asdw') 偏移量
T.count('asdw') 计数
nametuple('asdw',['name','age']) 有名元组扩展类型
元组的实际应用
元组支持字符串和列表的一般序列操作
元组的特殊语法:逗号和圆括号
如果你想要圆括号内单一对象是元组对象而不是一个简单的表达式。想要对python进行特备说明,关闭圆括号前加一个逗号
作为一种特例,在不会引起二义性的情况下,Python允许忽略元组的圆括号。
一般来说,在一下的情况下,必须对元组字面量使用圆括号
圆括号不可省略,出现在一个函数调用中,或是嵌套在一个更大的表达式中
逗号不可省略,嵌套在一个更大的列表,字典,或者在Python2.X的print语句中
转换,方法和不可变性
除了字面量语法外,预祝的操作和字符串及列表是一致的。值得注意的是,当+,*,以及分片作用于元组是,会返回新的元组,并且元组不提供字符串列表和字典中的方法。例如,如果你想对元组进行排序,通常先得将它转换为列表从而使其成为一个可变对象,才能使用排序方法调用,或者使用内置函数sorted,它接受任何序列对象,
这里使用list和tuple内置函数用来将对象转换成列表,或转为元组。实际上,这两个调用都会生成新的对象,但总结果等效于转换
列表推导也可以用来转换元组
列表推导的本质是序列操作,它们总会创建新的列表,但它们也可以用于遍历包括元组,字符串以及其他列表在内的任何程序对象,列表推导甚至可以作用在某些并非实际存储的序列上,任何可迭代对象都可以,包括可以自动读取的文件,考虑到这一点,列表推导实际上可以被视为一种迭代工具。
元组多多少少有几个属于自己的方法,如index和count
要注意元组的不可变性只适用于顶层而非其内容,
为什么有了列表还要元组
元组列表相对比,会发现其功能都是类似的,但是元组方法更少,不够灵活,不可变。
但是元组的不可变性提供了某种一致性,可以确保元组在程序中不会被另一个引用修改,而列表就没有这样的保证了,类似于其他语言中常量的概念,
列表是适用于需要进行修改的有序集合,而元组能够处理其他固定关系的情况,
重访记录,有名元祖
元组可以胜任列表在记录方面的角色
就像列表一样,字段的序号不能像字典的键一样携带关于这个字段的信息。
在需要时,可以将字典的一部分转换为元组
如果做一些额外的工作,可以实现一个同时提供序号和键两种访问方式的对象,例如,namedtuple工具实现了一个增加逻辑的元组扩展类型,能同时支持使用序号和属性名访问组件,也可以转换成使用键的类字典形式的访问。有名元组的属性名来自类,因此并不与字典的键完全一样,但它们都方便记忆:
为了构造一个namedtuple需要两个参数,分别是tuple的名字和其中域的名字。
在需要时,可以转换为一个类字典的基于键的形式
有名元组是一个元组,类,字典的混合体。其意义在于将元组实现键值对,且元组不可变,因此实现类字典的不可变键值结构,且具有顺序,可以通过偏移量索引。
文件
内置函数open能够创建一个python文件对象作为到计算机上一个文件的链接。在调用open后,可以通过返回的文件对象的方法·,在程序和相应文件还在建来回传递串形式的数据。
常见的文件操作
操作 解释
output = open(r'C:\asdw','w') 创建输出文件(‘w’代表写入)
input = open('data','r') 创建输入文件('r'代表读入)
input = open('data') 与上一行相同,('r'是默认值)
astring = input.read() 把整个文件读进一个字符串
astring = input.read(N) 读取接下来的N个字符(一个或多个)到一个字符串
astring = input.readline() 读取下一行(包含\n换行符)到一个字符串
alist = input.readlines() 读取整个文件到一个字符串列表(包含\n换行符)
output.write(astring) 将字符串写入文件
output.wrtielines(alist) 将列表中所有字符串写入文件
output.close() 手动关闭(当文件收集完成会替你关闭文件)
output.flush() 把输出缓冲区刷入硬盘中,但不关闭文件
anyfile.seek(N) 将文件位置移动到偏移量N处以便进行下一个操作
for line in open('data'): use line 文件迭代器逐行读取
open('f.txt',encoding = 'latin-1') Unicode文本文件
open('f.bin','rb') 字节码文件
打开文件
为了打开一个文件,程序会调用内置函数open,传入参数首先是外部文件名,接着是文件的处理方式,open函数返回一个文件对象,这个文件对象带有可以传输数据的方法
afile = open(filename,mode)
afile.method()
open函数的第一个参数是外部文件名,它可能含有一个与平台相关的绝对或相对目录路径前缀,如果没有这个目录路径,文件被默认存在当前工作目录查下(程序所运行的目录)。
open的第二个参数是处理模式,通常用字符串r表示以输入模式打开文件(默认值),w表示以生成模式生成并打开文件,a表示在文件末尾追加内容并打开文件(如像日志文件中添加内容),处理模式参数也可以指定为其他选项
在模式字符串中加上b可以进行二进制数据处理
加上+意味着被打开文件的同时支持输入输出
open函数的前两个参数必须都是python的字符串,第三是可选参数,它能够用来控制输出缓存,传入0意味着输出无缓冲(写入方法调用是立即传给外部文件)
使用文件
一旦使用open函数产生了一个文件对象,就可以调用它的方法来读取或写入对应的外部文件,在任何情况下。文件的文本在python程序中都采用字符串的形式。读取文件会返回字符串形式的文本,写入文件时的文本作为字符串被传入write方法。读和写的方法有很多中。
一些基础用法的提示:
文件迭代器最适合逐行读取
今天从文本文件逐行读取的追加方式就是根本不要读取该文件,文件也有一个迭代器,可以在for循环,列表推导或其他迭代上下文中自动逐行读取文件。
内容是字符串,不是对象
从文件中读取的数据返回到程序时是一个字符串,使用如果字符串不是你所需要的,就需要将它转换成其他类型的Python对象。同样,写入文件时,Python不会自动把对象转换成字符串,这和print语句不通,你必须传入一个已经格式化的字符串。
文件时被缓存以及可定位的
在默认情况下,输出文件总是被缓冲的,这意味着写入的文本可能不会立即自动从内存中转移到硬盘,除非关闭一个文件或运行其flush方法,才能强制被缓冲的数据进入硬盘。Python文件也是在直接偏移量的基础上随机访问的,它们的seek方法允许程序跳转到指定的文字读取和写入
close通常是可选的,回收时会自动关闭
调用文件close方法将会终止与外部文件的谅解,释放操作系统的资源,以及将内存中的缓冲内容输出到硬盘并清空缓冲区。一旦对象不被引用,那么这个对象的内存空间会自动被回收。当文件被回收时,那么这个文件的内存空间就会被自动回收。
文件的实际应用
这里以写的方式创建了一个不存在的文件,写入两行话,然后关闭了文件。
注意打开文件是隐式的,不是我敲下回车弹出这个txt,而是在对应的存储空间创建了这个文件,这个txt界面是我手动打开展示的,
write会返回写入的字符数,它不会自动添加换行,换行需要我们手动添加,
刚刚用close关闭了外部文件链接,但是记事本的图形界面没有关闭,再次链接写入语句然后笔记本没有更新,是因为数据在缓存中没有存储到硬盘。
这里显示了三行,但是之前写入数据去哪里,因为是以w方式写入文件,如果想要续写应该使用a。
如果想要逐行扫描一个文本文件,文件迭代器往往是最佳选择。
文本和二进制文件
严格来讲,之前示例使用的文本文件。在Python中,文件类型都有open的第二个参数模式字符串决定,模式字符串包含一个b表示二进制,Python总是支持文本和二进制文件。但是二者之间有明显区别
文本文件把内容表示为常规的str字符串,自动执行Uniden编码和解码,并且每人执行行末转换
二进制文件把内容表示为一个特殊的bytes字节串类型,并且允许程序不修改地访问文件内容
当读取一个二进制数据文件是,会得到一个bytes对象,表示绝对字节值的较小整数的一个序列
此外,二进制文件不会对数据执行任何换行符转换,在Python3.X中写入和读取时,文本文件会默认执行对\n的来回转换,并采用Unicode编码。
在文件中存储Python对对象:转换
文件数据在程序中一定是字符串,而写入方法不会自动做出任何到字符串的转换工作。
可以看到写入数据时只能是字符串类型。
现在我们将数据类型都变成了字符串存入了文本
这里我忘了添加换行符,手动填一下,方便下一步
读取文件
我们需要使用其他的转换工具,将文本文件中的字符串转换为真正的Python对象,将于Python不自动将字符串转换为其他类型的对象,我们需要使用诸如索引,加法等普通对象工具
介绍一些字符串方法,
这里可以去末尾多余空格
这里将字符串分隔按照我们的需求
这里还是先打开文件,去除末尾无用的空格,接下来按照换行符分隔为列表。
这里注意之前的方法都是返回新的字符串,需要命名引用。
这次得到我们需要的结果。现在可以对其转换,
这时发现了一些错误,我们在将列表元组还原是没有得到想要的结果,这是因为引号内的内容是字符串,属于序列,list和tuple方法是将序列转换为相应的列表元组。
这时需要新的函数。
eval能把字符串当作可执行程序代码,从技术上来讲,就是一个含有Python表达式的字符串。
存储Python原生对象:pickle
使用eval可以吧字符串转换为对象,因此它是一个功能强大的工具,事实上,它有时过于强大,eval会高高兴兴地执行Python的任何表达式,只要给予必要的权限,甚至可能会删除计算机上所有文本的表达式,如果你真的想要存储Python原生对象,但又无法信赖文件的数据来源,那么python标准库pickle模块将是个理想的选择
pickle模块是能够让我们直接在文件中存储几乎任何Python对象的工高级工具,同时并不需要对字符串进行来回转换,就像是超级通用的数据格式化和解析工具。
如想要在文件中存储字典,可以直接使用pickle
之后,在想要取回字典时,只需要再次使用pickle重建即可
无需手动切分或转换,pickle模块会执行所谓的对象序列化,也就是对象与字节字符串之间的相互转换
用json格式存储Python对象
json是一种新兴的数据交换格式,它既是语言无关,也支持多种系统。json具有强大的可移植性。
json提供了将一类特定的Python对象序列化,从而实现存储和传输的方式。
具有嵌套结构的字典与JSON数据十分类似,尽管Python的变量和表达式支持更丰富的结构选项,
这是一个常见的Python字典格式。然后我们使用json模块将其转换
在Python对象和文件中,json数据字符串之间的相互转换都是非常直接的,在被存入文件之前,数据都是简单的Python对象,当你从文件中读取对象时,json模块将他们从JSON表示重建成Python对象
存储打包二进制数据:struct
struct模块能够构造并解析打包二级数据,能够把文件中的字符串转换为二进制数据
例如,要生成一个二进制数据文件,可以用wb模式打开,并将一个格式化字符串和几个Python对象传给struct。
Python会创建一个我们通常写入文件的二进制bytes数据字节串,它主要由不可打印字符的十六进制转义组成,就是二进制文件。要把值解析成一般的Python对象,可以直接读取字符串,并使用相同格式字节串解压即可。python能够把值提取出来转换为普通的Python对象,下面以整数和字符串为例
这里我查询了一下这些参数的意义
可以看到fmt是给定格式,那么‘>i4sh’应该是确切的格式,
第一位字符『>』,怎么理解呢?
为了同c中的结构体交换数据,要考虑有的c或c++编译器使用了字节对齐,使用方法是放格式串的第一位,有 @ = < > ! 共5种,具体去后面附的链接中查,就是这么规定的。
『i4sh』的意义在C数据结构和Python中的数据结构如下:
i ----> int ---> integer ---> 7
4s ----> char ---> string ---> 'spam'
h ---> unsigned short ---> integer ---> 8
注:每个格式前可以有一个数字,表示个数,比如上面的4s
参考官网资料:7.3. struct
>i4sh这部分原作者:临书
链接:https://www.zhihu.com/question/50704558/answer/122388467
可以使用二进制文件的处理模式,‘wb’,'rb'整体处理更简单的二进制文件如图片或视频文件,而无需将他们解压,你的代码就可以将他们原封不动地传给其他文件或工具
文件上下文管理器
我们可以把文件处理代码包装到一个逻辑层中,以确保在退出后一定会自动关闭文件,同时可以满足将其输出缓存区内容写入磁盘,而不是依赖于垃圾回收时的自动关闭
with上下文管理器方案在所有Python版本中都能保证操作系统资源的释放,而且对于确保刷新输出文件缓冲区更加有用,与更常用的try语句不同,with则只局限于能够支持它的协议对象,
其他文件工具
open函数以及其返回的文件对象是Python脚本中通向外部文件的主要接口,但Python工具集中还有其他类似可用的文件工具。
例如:
标准流
在sys模块中预先打开文件对象,如sys.stdout
os模块中的描述文件
文件的整数参数,能够支持如文件锁定之类的较低级工具
套接字,管道和FIFO文件
用于同步进程或者通过网络进行通讯的类文件对象
通过键来存储的文件,如shelve模块
通过键直接存储经过pickle模块序列化的不可变的Python对象
shell命令流
像os.popen和subprocess.Popen这样的工具,支持shell命令处理,并调取和写入到标准流
核心类型复习与总结
按照分类,一些对象拥有共同的操作,例如,字符串,列表和元组都拥有拼接长度和索引等序列操作
支持可变对象(列表,字典,集合)可以找原位置修改,我们不能在原位置修改数字,字符串以及元组
文件只导出方法,因此可变性并不真的适用于它们,但处理文件的时候,它们的状态可能会改变,但这与Python核心类型所描述的可变性完全是两种含义
Python中的数字包含了所有数字类型,整数,浮点数,复数,小数,分数
Python中的字符串包括str,byte是和Unicode
集合很像是个没有值只有键的字典,但他们不能进行映射,也没有顺序,因此,集合本身一个映射或者序列类型。
除了类型分类操作,Python的所有类型都有可调用的方法,这些方法通常属于每种特定的类型。
对象分类
对象类型 分类 是否可变
数字 数值 否
字符串 序列 否
列表 序列 是
字典 映射 是
元组 序列 否
文件 扩展 N\A
集合 集合 是
forzenset(不可变变集合) 集合 否
bytearray(可变字符串) 序列 是
对象灵活性
复合对象类型,一般来说
列表,字典和元组可以包含任意种类的对象
集合可以包含任店不可变类型
列表,字典和元组可以任意嵌套
列表,字典,集合可以动态的扩大和缩小
引用VS复制
赋值操作总是存储对象的引用,而不是这些对象的副本
引用是其他语言中指针的更高级模拟,这些语言在使用引用时不断地跟踪他们的情况,虽然你不能获取引用本书,但是可以在不止一个地方存储相同的隐痛,可以在程序范围内任何地方传递大型对象而不必在途中进行开销巨大的复制操作。然而,如果确实需要复制,可以明确要求
没有参数传递的分片表达式(L[ : ])可以复制序列
字典,集合或列表的copy方法可以复制一个字典、集合或列表
一些诸如list和dict的内置函数,可以进行赋值(list(L),dict(D),set(S))
copy标准库模块能够在需要时创建完整副本
无参数的分片以及字典的copy只能够进行顶层复制,也就是说,它们不能够赋值嵌套的数据结构。
如果需要创建一个深层嵌套的数据结构完整的、完全独立的,那么就要使用copy模块的deepcopy
比较,等价性和真值
所有的Python对象也都支持比较操作,测试等价性,相对大小等。
Python有两种测试等价性的方式:
== 运算符测试值的等价性,Python会运行等价性测试,并递归比较所有的内嵌对象
is表达式测试了对象的同一性,Python测试两者是否是同一个对象(也就是说,在除尘器中的相同地址)
Python按照下面的方式来比较不同的类型
数字在转换成必要的公共最高级类型后,比较数值的相对大小
字符串按照字母字典顺序比较(按照ord函数返回的字符集编码顺序),一个字符接一个字符地比较直到末尾或发现第一个区别
列表和元组从左到右对每个组件的内容进行比较,而且对嵌套结构的比较是递归的,直到末尾或发现第一个区别
集合是相等的,当且仅当它们含有相同的元素。集合的相对大小比较采取子集和超集的检验标准
字典通过比较排序后的(key,value)列表来判断是否相同,Python3.X不支持字典的相对大小比较
非数字混合类型相对比较在Python3.X会报错
Python中True和False的含义
在Python中,0代表假,整数1代表真。Python也把任何空数据类型视为假,把任何非空数据类似视为真。更一般的,真和假的概念是Python中每个对象的固有属性,每个对象非假即真
数字如果等于零则为假,否则为真
其他对象如果为空就是假,否则为真
对象真值的例子
对象 值
'spam' True
"" False
[1,2] True
[] False
{'a':777} True
{} False
1 True
0.0 False
None False
常见的
假设X是字符串,上下两个表达式的含义是相同的。
None对象
None是Python中一个特殊对象,总是被认为是假,是Python中元组特殊数据类型的唯一值,一般都起到空占位符的作用。
None表示意味着未定义。None是某些内容,而不是没有内容,None是一个真正的对象,并且有一块真实的内存,Noce是Python给定的一个内置名称。它同时函数默认的返回值,如果函数没有运行到return语句就结束的话
bool类型
python的布尔类型bool只不过是扩展了python中的真假的概念,正如第五章所述,内置的True和False关键字只是转述1和0的定制版本而已。
当显示的用在真假测试时,True和False关键字就变成了1和0,但他们使得程序员的意图更加明确
交互式命令行模式下运行的布尔测试的结果被打印成单词True和False,而不是1和0,使得程序的结果更加明确
Python还提供了一个内置函数bool,他可以显示的测试一个对象的布尔值
Python的类型
内置类型陷阱
赋值创建引用,而不是复制
重复会增加层次深度
由于L在赋值给Y时是被嵌套的,因此Y中包含了指回原本L的列表引用
注意循环数据结构
不可变类型不可用在原位置改变
如果需要的话,必须通过分片,拼接等操作来创建一个新的对象,再赋值回原本的引用
本章小结
元组支持所有一般的序列化操作,它们拥有一些方法,由于不可变性而不能进行任何的原位置修改,以及通过有名元祖进行扩展。
文件是由内置的open函数返回的对象,并且提供读写数据的方法
介绍了Python对象如何在字符串之间进行来回转换,而且也了解到pickle,json和struct模块用法。