文章目录
IO库
在计算机中,什么是流?
计算机中的流其实是一种信息的转换,它是一种有序流,因此相对于某一对象,通常我们把对象接收外界的信息输入(Input)称为输入流,相应地从对象向外输出(Output)信息为输出流,合称为输入/输出流(I/O Streams)
对象间进行信息或者数据的交换时内总是先将对象或数据转换为某种形式的流,再通过流的传输,到达目的对象后再将流转容换为对象数据。所以,可以把流看作是一种数据的载体,通过它可以实现数据交换和传输
流(stream) 是与磁盘或其它外围设备关联的数据的源或目的地
IO库
IO是用来处理各种 I/O 类型的主要工具,比如,打开文件、读取数据、删除文件,I/O类型主要分为:
可变字符串
本节主要写与字符串的相关用法,如果想了解更多,可以参考本节末的其他用法
函数 | 说明 |
---|---|
io.StringIO(initial_value=’’, newline=’\n’) | 在内存中创建文件,用于文本 I/O 的内存数据流 |
s.getvalue() | 返回对象s中的所有数据 |
s.flush() | 刷新流写入缓冲区(如果适用)。这对只读和非阻塞流不起作用 |
s.close() | 刷新并关闭此流 |
s.closed | 如果流已关闭,则返回 True |
s.isatty() | 如果流是交互式的(即连接到终端/tty设备),则返回 True |
s.seek() | 设置当前流的位置 |
tell() | 返回当前流的位置 |
s.write(s) | 从读写位置将参数s写入给对象s。参数s为str或unicode类型。 使用该函数后流的位置会移动 |
s.writelines(list) | 从读写位置将list写入给对象s。参数list为一个列表,列表的成员为str或unicode类型。 使用该函数后流的位置会移动 |
s.read([n]) | 参数n( int类型 )限定读取长度 缺省状态为从当前流的位置读取对象s中存储的所有数据 使用该函数后流的位置会移动 |
s.readline() | 从流中读取并返回一行 使用该函数后流的位置会移动 |
s.readlines() | 从流中读取并返回包含多行的列表 使用该函数后流的位置会移动 |
s.truncate([size]) | 将流的大小调整为给定的 size 个字节(如果未指定 size 则调整至当前流的位置) |
⭐注:要关注流的位置,否则容易出现空白或覆盖字符串的情况
#可变字符串
import io
str_1='12345678'
s = io.StringIO(str_1) #在内存中创建文件
# 读
print(s.tell()) #读取当前流的位置 →0
print(s.read()) #从当前流的位置读取s →12345678
print(s.tell()) #读取后,流的位置变到了→8
print(s.read()) #再读取 → [空白]
print(s.getvalue()) #取出s的所有数据→12345678
s.seek(0) #重新设置流的位置至→0
print(s.read(6))#从当前流的位置读取长度为6的s →123456
print(s.tell()) #流的位置到了→6
s.seek(0) #重新设置流的位置至→0
print('-------------------------------')
#isatty
print(s.tell()) #读取当前流的位置 → 0
print(s.isatty()) #查看当前流是否是交互式的 → False
print('-------------------------------')
#写
print(s.tell()) #读取当前流的位置 → 0
s.seek(8) #设置流的位置→8
s.write('90') #从当前位置写入
print(s.tell()) #读取当前流的位置 → 10
print(s.getvalue())#取出s的所有数据→1234567890
s.seek(0) #重新设置流的位置至→0
print('-------------------------------')
#切断
print(s.getvalue()) #切断前:取出s的所有数据→1234567890
s.truncate(6) #当前流的位置→0,保留6个长度
print(s.getvalue()) #切断后:取出s的所有数据→123456
s = io.StringIO(str_1) #重建s
print(s.getvalue()) #取出s的所有数据→12345678
s.seek(3) #重新设置流的位置至→3
print(s.tell()) #读取当前流的位置 → 3
s.truncate() #没有填SIZE,所以默认SIZE=流的位置3
#相当于s.truncate(3)
print(s.getvalue())#取出s的所有数据→123
print('-------------------------------')
s.flush() #刷新流写入缓冲区
s.close() #刷新并关闭此流
# 读
0
12345678
8
12345678
123456
6
-------------------------------
#isatty
0
False
-------------------------------
#写
0
10
1234567890
-------------------------------
#切断
1234567890
123456
12345678
3
123
-------------------------------
其他用法
参考官网:io — Core tools for working with streams
组合数据类型
计算机不仅对单个变量表示的数据进行处理,实际应用中,计算机更需要对一组数据进行批量处理,我们把能够表示多个数据的类型叫做组合数据类型,它们通常分为:
序列
序列是一种数据存储方式,在内存中序列就是一块用来存放多个值的连续内存空间,例如序列[1,2,3,4]
>>>a = [1,2,3,4]
>>>for i in range(4):
print(id(a[i]))
print(type(a[i]))
print(a[i])
print(id(a))
140722051732512
<class 'int'>
1
140722051732544
<class 'int'>
2
140722051732576
<class 'int'>
3
140722051732608
<class 'int'>
4
2324808491592
它在内存中是这样存储的:
可以从上图看出序列中存储的是整数对象的地址,而不是它的值
列表
列表:用于存储任意数目、任意类型的一个集合,它包含多个元素的有序连续的内存空间,属于序列类型
列表的创建
列表类型用中括号 [ ]表示,也可以通过list(x)函数将集合或字符串类型转换成列表
a = [1,['???',32],'l2']
a = list(range(11))
列表中的这些人名是列表的元素,元素可以是任意类型,如数字、字符串、字典或列表本身
生成器推导式创建列表
range()函数
函数 | 说明 |
---|---|
range([start],end,[step]) | 返回一个range对象,start起始数字(默认0),end结尾数字,step步长 |
>>>a = list(range(3,15,2))
>>>print(a)
[3, 5, 7, 9, 11, 13]
>>>a = list(range(3,15,-2))
>>>print(a)
[15, 13, 11, 9, 7, 5]
>>>a = [x**2 for x in range(20,1,-1) if x%9==0]
#[算数表达式 for x in range(...) 条件]
>>>print(a)
[324, 81]
列表对象的常用函数
函数 | 要点 | 说明 |
---|---|---|
list.append(x) | 增加元素 | 将元素x加到列表list尾部 |
list.extend(alist) | 增加元素 | 将列表alist所有元素加到列表list尾部 |
list.insert(index,x) | 增加元素 | 在列表list指定位置index插入元素x |
list.remove(x) | 删除元素 | 删除列表list中首次出现的指定元素x |
list.pop([index]) | 删除元素 | 删除并返回列表list指定位置index处的元素,默认是最后一个元素 |
list.clear() | 删除全部元素 | 删除list中所有元素,并不是删除列表对象 |
list.index(x) | 访问元素 | 返回x首次出现的索引位置,若没有x则报错 |
list.count(x) | 计数 | 返回指定元素x在列表中的出现次数 |
len(list) | 列表长度 | 返回列表中包含元素的个数 |
list.reverse() | 列表翻转 | 列表中所有元素反转 |
list.sort() | 排序 | 所有元素原地排序 |
list.copy() | 浅拷贝 | 返回列表对象的浅拷贝 |
列表元素的增加和删除
当列表增加和删除元素的时候,尽量只在列表的尾部添加或删除元素,这可以大大增加操作效率
append()
原地修改列表对象,真正的列表添加新的元素,速度最快
>>>a = [x**2 for x in range(20,1,-1) if x%9==0]
#[324, 81]
>>>a.append(5)
>>>print(a)
#[324, 81, 5]
加号添加元素
此方法并不是真正的添加尾部的元素,而是通过创建新的对象:将原列表的元素和新列表元素依次复制到新的列表对象中,涉及大量的操作,如果任务量大则不推荐使用
>>>a = [20,1]
>>>print(id(a))
1656394179144
>>>a= a+[30]
>>>print(a)
[20, 1, 30]
>>>print(id(a))
1656423653576 #地址发生了变化,产生新的对象
extend()
将目标的所有元素添加到本列表尾部,属于原地操作,不创建新的列表对象
>>>a = [20,1]
>>>print(id(a))
1391004639816
>>>a.extend([50,6])
>>>print(a)
[20, 1, 50, 6]
>>>print(id(a)) #地址不变,还是原来的对象
1391004639816
insert()
将指定元素插入到列表对象的任意指定位置,插入后会让所有的元素移动,影响速度,任务量大的时候尽量避免使用,类似发生这种移动的函数还有:remove()、pop()、del()
>>>a = [20,1]
>>>a.insert(1,50)
>>>print(a)
[20, 50, 1]
乘法扩展
通过乘法多次复制列表元素
>>>a = [20,1]
>>>a=a*3
>>>print(a)
[20, 1, 20, 1, 20, 1]
del()
删除指定位置的元素,删除的时候后面的元素会依次向前拷贝
>>>a = [20,1]
>>>del a[1]
>>>print(a)
[20]
pop()
删除并返回指定位置的元素,如果没有指定则默认操作最后一个元素
>>>a = [20,1]
>>>a.pop()
>>>print(a)
[20]
remove()
删除首次出现的指定元素,若不存在则会异常
>>>a = [20,1.5,466.5,4,8,20]
>>>a.remove(20)
>>>print(a)
[1.5, 466.5, 4, 8, 20]
列表元素的访问和计数
通过索引直接访问元素
我们可以通过索引直接访问元素,索引区间在[0,列表长度-1],超过这个区间范围就会异常
>>>a = [20,1.5,466.5,4,8,20]
>>>print(a[3])
4
index()
index()可以获取元素首次出现的索引位置,若没有x则报错
语法:index(value,[start],[end]),start和end指定搜索范围
>>>a = [20,1.5,466.5,4,8,20]
>>>a.index(20,1,len(a)+1)
>>>print(a.index(20,1,100))
5
count()
count()可以获得指定元素在列表中出现的次数
>>>a = [20,1.5,466.5,4,8,20,20,5,6,1,20]
>>>print(a.count(20))
4
列表长度
len()可以返回列表的长度,也就是列表中包含元素的个数
>>>a = [20,1.5,466.5,4,8,20,20,5,6,1,20]
>>>print(len(a))
11
列表成员资格判断
列表成员资格判断指的是列表中是否存在指定的元素,可以使用count()看看是否存在,也可以用in判断
>>>a = [20,1.5,466.5,4,8,20,20,5,6,1,20]
>>>print(100 in a)
False
>>>print(a.count(100))
0
切片操作
列表的切片操作和字符串类似,其操作格式为:
list[起始偏移量start : 终止偏移量end : [步长step] ]
当步长不写时,可以顺便省略步长前面的冒号
操作和说明 | 示例 | 结果 |
---|---|---|
[ : ]提取整个列表 | [10,20,30][:] | [10,20,30] |
[start: ]从start索引开始到结尾 | [10,20,30][1:] | [20,30] |
[ :end ]从头到end-1 | [10,20,30][:2] | [10,20] |
[start: end]从start到end-1 | [10,20,30,40][1:3] | [20,30] |
[start: end :step]从start到end-1,步长是step | [10,20,30,40,50,60,70] [1:6:2] | [20,40,60] |
切片的时候也可以用负数:
示例 | 说明 | 结果 |
---|---|---|
[10,20,30,40,50,60,70][-3:] | 倒数三个 | [50,60,70] |
[10,20,30,40,50,60,70][-5: -3] | 倒数第五个到倒数第三个 | [30,40] |
[10,20,30,40,50,60,70][::-1] | 步长为负,从右到左反方向提取 | [70, 60, 50, 40, 30, 20, 10] |
⭐注:切片操作的时,起始偏移量和终止偏移量不在合法的范围内也会报错,起始偏移量小于0,则会当作0,终止偏移量大于 长度-1 会被当成-1
列表的遍历
>>>a=[10,20,30,40,50,60,70]
>>>for x in a:
print(x,end=' ')
10 20 30 40 50 60 70
列表排序
>>>a=[10,20,30,80,50,60,70,40]
>>>print(id(a))
2999602012744
>>>a.sort() #升序排列
>>>print(a)
[10, 20, 30, 40, 50, 60, 70, 80]
>>>print(id(a))
2999602012744 #地址不变
>>>a.sort(reverse=True) #降序排列
>>>print(a)
[80, 70, 60, 50, 40, 30, 20, 10]
>>>import random
>>>random.shuffle(a)#打乱顺序
>>>print(a)
[20, 10, 60, 50, 40, 80, 70, 30]
#建新列表排序
>>>a=[10,20,30,80,50,60,70,40]
>>>print(id(a))
2107040293448
>>>a=sorted(a)
>>>print(a)
[10, 20, 30, 40, 50, 60, 70, 80]
>>>print(id(a)) #地址变了
2107040293512
reversed()返回迭代器
内置函数reversed()也支持进行逆序排列,与reverse()不同的是reversed()不会对原列表做修改,只会返回一个逆序排列的迭代器对象
>>>a=[10,20,30,80,50,60,70]
>>>b=reversed(a)
>>>print(list(b))
>
[70, 60, 50, 80, 30, 20, 10]
>>>print(b)
<list_reverseiterator object at 0x000001E9B66161D0>
>>>print(list(b)) #迭代器只能用一次
[]
列表相关的其他函数
Max和Min
>>>a=[10,20,30,80,50,60,70,40]
>>>print(max(a))
80
>>>print(min(a))
10
Sum
对数值型列表所有元素求和,对于非数值型的会报错
>>>a=[10,20,30,80,50,60,70,40]
>>>print(sum(a))
360
多维列表
二维列表
二维列表可以帮助我们存储表格数据,例如:
>>>a=[
['高小一',18,30000,'北京'],
['高小二',19,20000,'上海'],
['高小三',20,10000,'深圳']
]
>>>for x in range(len(a)):
print(a[x],end='\n') #换行打印
['高小一', 18, 30000, '北京']
['高小二', 19, 20000, '上海']
['高小三', 20, 10000, '深圳']
内存结构图如下:
遍历二维列表
# 取出二维元素
>>>a=[
['高小一',18,30000,'北京'],
['高小二',19,20000,'上海'],
['高小三',20,10000,'深圳']
]
>>>print(a[2][0])
高小三
# 遍历二维列表
>>>a=[
['高小一',18,30000,'北京'],
['高小二',19,20000,'上海'],
['高小三',20,10000,'深圳']
]
>>>for x in range(len(a)):
for i in range(len(a[x])):
print(a[x][i], end='\n')
高小一
18
30000
北京
高小二
19
20000
上海
高小三
20
10000
深圳
>>>a=[
['高小一',18,30000,'北京'],
['高小二',19,20000,'上海'],
['高小三',20,10000,'深圳']
]
>>>for x in range(len(a)):
for i in range(len(a[x])):
print(a[x][i], end='\t')
print()
高小一 18 30000 北京
高小二 19 20000 上海
高小三 20 10000 深圳
元组
列表属于可变序列,但元组属于不可变序列,所以在元组中不能修改元素、增加元素或删除元素,故只要学习元组的创建和删除,元组中元素的访问和计数就差不多了
元组支持以下操作:
1.索引访问
2.切片操作
3.连接操作
4.成员关系操作
5.比较运算操作
6.计数:长度、最大最小值、求和
⭐注:①元组的访问和处理速度比列表快②元组和整数、字符串一样,可以作为字典的键(因为数据类型不可变),但列表不能作为字典的键使用
元组的创建
元组通过小括号 ( ) 创建 小括号可以省略
a=(1,2,3)
#等价于
a=1,2,3
⭐注:当元组只有一个元素的时候,解释器会把元组解释成一个数而不是元组
也可以通过tuple()函数创建
>>>b=tuple('123123')
>>>print(b)
('1', '2', '3', '1', '2', '3')
函数 | 说明 |
---|---|
tuple() | 接收列表、字符串、其他序列类型、迭代器等生成元组 |
list() | 接收元组、字符串、其他序列类型、迭代器等生成列表 |
生成器推导式创建元组
从形式上看,生成器推导式创建元组与列表类似,只不过推导式创建元组用的是小括号
⭐注:生成器推导式生成的不是列表,也不是元组,而是一个生成器对象
我们可以通过生成器对象转化成列表或元组,再用生成器对象的__next__() (前后都是两个下划线)方法遍历,或直接作为迭代器对象使用,但需要注意的是只能使用一次,要是想再用只能重建该生成器
>>>a = (x*6 for x in range(9) if x%3==0)
>>>print(tuple(a))
(0, 18, 36)
a = (x*6 for x in range(9) if x%3==0)
>>>print(a.__next__())
0
>>>print(a.__next__())
18
>>>print(a.__next__())
36
>>>print(a.__next__()) #只有3个,取完了就没有了
Traceback (most recent call last):
File "C:/Users/Leonardo/PycharmProjects/untitled/1.py", line 9, in <module>
StopIteration
元组的删除
>>>b=tuple('123123')
>>>del b #删除
元组元素的访问和计数
元组元素的访问和列表一样,通过索引或切片访问
计数、最值、求和和列表的使用方法一样,这里就不一一赘述了
>>>b=(1,2,3,4,5,6)
>>>print(b[3])
4
>>>print(b[3:])
(4, 5, 6)
>>>print(b[::-1])
(6, 5, 4, 3, 2, 1)
⭐注:列表关于排序的方法list.sorted()是修改原列表对象,元组没有这个方法,若想要对元组排序只能用 sorted()函数,生成新的对象
>>>b=(90,5,66,22,1,33,555,652)
>>>print(sorted(b))
[1, 5, 22, 33, 66, 90, 555, 652] #排序后变成列表了
>>>print(sorted(b,reverse=True))
[652, 555, 90, 66, 33, 22, 5, 1]
Zip
Zip(列表1,列表2,列表3, … ) 可以将多个列表对应位置的元素组合成元组,并返回这个Zip对象
>>>a = [1,2,3]
>>>b = [4,5,6]
>>>c = [7,8,9]
>>>d = zip(a,b,c)
>>>print(d)
<zip object at 0x00000226FD6F1CC8> #新对象
>>>print(list(d)) #把对象变成列表并打印
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
基本运算符(补充)
运算符 | 描述 |
---|---|
| | 按位或 |
^ | 按位异或 |
& | 按位与 |
>> 、<< | 移位 |
~ | 按位反转 |
<<= | 左移赋值 |
>>= | 右移赋值 |
|= | 按位或赋值 |
&= | 按位与赋值 |
^= | 按位异或赋值 |
⭐Python不支持自增++和自减–
位运算
# 十进制转换成二进制 bin(num)
# 十进制转换成八进制 oct(num)
# 十进制转换成十六进制 hex(num)
# 二、八、十六进制转换成十进制:
# int(num,base=2/8/16)
a=0b11001 #25
b=0b01000 #8
#按位或:只要有一个1,结果就是1
print(bin(a|b)) #10→1 11→1 00→0 00→0 10→1
#也就是 11001
#按位异或:相异为1 相同为0
print(bin(a^b))#10→1 11→0 00→0 00→0 10→1
#也就是 10001
#按位与:只要有一个0,结果就是0
print(bin(a&b))#10→0 11→1 00→0 00→0 10→0
#也就是 01000
移位
'''
<< 箭头向左就是向左移位
>> 箭头向右就是向右移位
'''
#二进制:
a = 0b0001 # 十进制对应1
print(bin(a<<1)) #0b0010 1向左移动了1位
# 十进制对应2=1*2
print(bin(a<<2)) #0b0100 1向左移动了2位
# 十进制对应4=1*2*2
print(bin(a<<3)) #0b1000 1向左移动了3位
# 十进制对应8=1*2*2*2
#十进制:
print(1<<1) #2
print(1<<2) #4
print(1<<3) #8
'''
二进制每左移1位就乘一次2,
这种乘法的速度比普通的乘法快得多
'''
优先级(补充)
当出现多个运算符时,Python 会:
⭐注:在实际应用中:
- 复杂表达式一定要加括号
- 乘除>加减>位运算符>比较运算符>赋值运算符>逻辑运算符