Set 集合
Set是一个无序而且不重复的元素集合。下面看看他有哪些基本功能
创建集合
>>> s1 = {11,22} s2 = set() s3 = set([11,22,33,4]) print(s1,s2,s3) ------------------- {11, 22} set() {33, 11, 4, 22}
把列表转换成集合,注意列表中重复的元素只保留一次
>>> li = [11,22,11,22] s1 = set(li) print(s1) --------------- {11, 22}
add给集合添加元素,clear清除集合的内容
>>> s = set() print(s) s.add(123) s.add(123) s.add(123) print(s) s.clear() print(s) --------------- set() {123} set()
两个集合A和B可以通过difference进行比较, 他会输出A中存在,而B中不存在的元素
>>> s1 = {11,22,33} s2 = {22,33,44} s3 = s1.difference(s2) print(s3) # A中存在,B中不存在 s3 = s2.difference(s1) print(s3) -------------- {11} {44}
symmetric_difference 可以输出两个集合中都不相同的元素
>>> s3 = s1.symmetric_difference(s2) print(s1) print(s2) print(s3) -------------- {33, 11, 22} {33, 44, 22} {11, 44}
如果后面跟了update,那么他的作用是直接替换到A的结果中,比如A中存在,B中不存在的结果是11,difference_update直接替换了A的内容;类似的如果我再执行symmetric_difference_update,他把A和B都不相同的内容保存在A中。
>>> s1.difference_update(s2) print(s1) s1.symmetric_difference_update(s2) print(s1) ------------ {11} {33, 11, 44, 22}
删除某一个元素可以用discard 或者 remove,但是如果该元素不存在,使用discard不会报错;而remove会抛出异常
>>> s1 = {11,22,33,1111} s1.discard(1111) print(s1) ---------- {33, 11, 22}
不报错
>>> s1 = {11,22,33,} s1.discard(1111)
抛出异常
>>> s1 = {11,22,33,} # s1.discard(1111) s1.remove(11111) -------------------- Traceback (most recent call last): File "<input>", line 3, in <module> KeyError: 11111
如果随机的删除一个元素,可以使用pop
>>> ret = s1.pop()##随机删 print(s1) print(ret) ------------- {11, 22} 33
求交集(Intersection)和并集(Union)
>>> s1 = {11,22,33} s2 = {22,33,44} s3 = s1.union(s2) print(s3) s3 = s1.intersection(s2) s1.intersection_update(s2) print(s3) ----------------- {33, 22, 11, 44} {33, 22}
update可以把其他的列表,元祖或者字符串的元素都并集进来,当然重复的不会添加
>>> s1 = {11,22,33} s1.add(11) s1.add(12) s1.add(13) li = [11,22,3,11,2] tup= (11,22,3,11,2) st = "alexalex" s1.update(li) s1.update(tup) s1.update(st) print(s1) ----------------------- {33, 2, 3, ‘l‘, ‘a‘, 11, 12, 13, 22, ‘x‘, ‘e‘}
小练习:两个字典,请判断出哪些key进行了变化,添加,删除和没变?
思路:把key单独转换成集合,然后通过判断集合元素是否存在判断添加和删除;通过交集判断哪些仍然存在为改变
>>> old_dict = { "#1": 8, "#2": 4, "#4": 2, } new_dict = { "#1": 4, "#2": 4, "#3": 2, } new_set = set(new_dict.keys()) old_set = set(old_dict.keys()) remove_set = old_set.difference(new_set) add_set = new_set.difference(old_set) update_set = old_set.intersection(new_set) print(remove_set,add_set,update_set) ---------------------- {‘#4‘} {‘#3‘} {‘#2‘, ‘#1‘}
文件的操作
打开文件的模式
- r ,只读模式【默认】
- w,只写模式【不可读;不存在则创建;存在则清空内容;】
- x, 只写模式【不可读;不存在则创建,存在则报错】
- a, 追加模式【可读; 不存在则创建;存在则只追加内容;】
"+" 表示可以同时读写某个文件
- r+, 读写【可读,可写】最常用
- w+,写读【可读,可写】清空之后再写,然后可以读之后写入的内容
- x+ ,写读【可读,可写】
- a+, 写读【可读,可写】只能在末尾更改,无法灵活指定位置
"b"表示以字节的方式操作
- rb 或 r+b
- wb 或 w+b
- xb 或 w+b
- ab 或 a+b
文件相关的函数
- fread() 无参数,读取全部;有参数,有b,按照字节读;有参数,无b,按照字符读
- tell(), 获取当前位置(字节)
- seek(), 调到指定的位置(字节)
- write(), 写入数据, 有b,按照字节;无b,按照字符写入
- close(), 关闭文件
- fileno(),文件描述符,判断文件是否有变化
- flush(), 强制刷新到内容
- readable(),判断是否可读
- readline(),按行读
- truncate(),截断,清空指针后面的内容
- for 循环
- with自动关闭文件
下面看看具体的例子
以只读方式打开一个文件db,注意编码我指定为utf-8,在utf-8里面 一个汉字等于3个字节;而在gbk里面,一个汉字占据2个字节。
>>> f=open(‘db‘,‘r‘,encoding="utf-8") data=f.read() print(data,type(data)) f.close() ------------------ sdf aa dddd <class ‘str‘>
我用只读字节的方式打开文件
>>> f=open(‘db‘,‘rb‘) data=f.read() print(data,type(data)) b‘sdf\r\naa\r\ndddd‘ <class ‘bytes‘>
下面的操作会抛出异常,因为我用字节的方式打开文件,当我尝试用字符串写入的时候,格式不兼容
>>> f=open("db",‘ab‘) f.write("hello") f.close() --------------- Traceback (most recent call last): File "<input>", line 2, in <module> TypeError: a bytes-like object is required, not ‘str‘
字节的方式添加信息
>>> f=open("db",‘ab‘) f.write(bytes("哈",encoding="utf-8")) f.close()
结果如下
sdf aa dddd哈
以读写方式打开文件,指定只读取前2个字符,注意这里没有指定b,因此是按字符读取;否则按照字节读取;tell()可以获取当前指针的位置(字节)
>>> f=open("db",‘r+‘,encoding="utf-8") data=f.read(2) print(data) print(f.tell())#获取当前指针位置(字节) sd 2
首先读取一个包含汉字的文件,如下所示,我指定了编码是utf-8,也指定了b,因此他是按照字符读取;这里他读取前2个字符“幸福”,然后因为utf-8一个汉字字符是3个字节,因此他的位置是6个字节处
>>> f=open("db",‘r+‘,encoding="utf-8") data=f.read(2) print(data) print(f.tell()) -------------- 幸福 6
如果这个时候我对这个文件做个修改,seek指定位置为第一个字节处,然后向后覆盖7777,这个时候他会把汉字(3个字节)硬拆开,导致的结果就是乱码
>>> f.seek(1) #当前指针位置开始向后面覆盖 f.write("7777") f.close()
结果如下所示
7777sdf aa dddd哈
flush函数强行把内存的数据写入硬盘保存,尽管还没有close
>>> f=open(‘db‘,‘a‘) f.write(‘123‘) f.flush() #没有close 但是内容写入了硬盘 input("hhhh")
readable顾名思义,判断一个文件是否可读,这里我一个只写方式打开的文件返回False
>>> f=open(‘db‘,‘w‘) print(f.readable()) --------- False
read()是读取全部,read(x)是读取前x个字节或者字符,而 readline()是读取一行,注意指针位置变化
f=open(‘db‘,‘r‘) f.readline()#注意指针的变化 f.readline()
truncate截断,指针后面的内容清空
>>> f=open(‘db‘,‘r+‘,encoding=‘utf-8‘) f.seek(3) f.truncate()
结果如下
sds
一个很常见的方式是通过for循环来读取每一行的内容,如下所示
>>> f=open(‘db‘,‘r+‘,encoding=‘utf-8‘) for line in f: print(line) ------------- sds 2 234 232sd
with自动关闭文件,这样不需要手动的使用 f.close()了
with open(‘db‘) as f: pass
Python2.7以后,可以同时操作两个文件,比如说,只读方式打开文件1,拷贝前10行文件到文件2里面
with open(‘db1‘,‘r‘,encoding="utf-8") as f1,open(‘db2‘,‘w‘,encoding=‘utf-8‘) as f2: times=0 for line in f1: times+=1 if times <=10: f2.write(line) else: break