0.本周知识点预览
- set
- 函数
- 文件
1.set 集合
1.set 方法解析
1.定义一个set
s1 = "caesary" set1 = set(s1) print(set1) l1 = [1,2,3,4] set2 = set(l1) print(set2) t1 = (1,1,1,2,3) set3 = set(t1) print(set3)
执行结果如下
{'y', 'e', 's', 'r', 'c', 'a'} {1, 2, 3, 4} {1, 2, 3}
总结:set集合有去重功能,类似awk数组;并且是无序的,类似字典。
2.add()
print(set1) set1.add("x") print(set1)
执行结果如下
{'e', 'a', 's', 'c', 'r', 'y'} {'e', 'a', 's', 'c', 'r', 'x', 'y'}
总结:add()方法可以在集合中添加一个元素。
3.clear()
print(set1) set1.clear() print(set1)
执行结果如下
{'s', 'a', 'r', 'c', 'e', 'y'} set()
总结:clear()方法可以清空一个集合。
4.copy()
print(set1) set4 = set1.copy() print(set1,set4)
执行结果如下
{'s', 'a', 'y', 'c', 'r', 'e'} {'s', 'a', 'y', 'c', 'r', 'e'} {'c', 'r', 'e', 's', 'a', 'y'}
总结:copy()可以浅拷贝一个集合。
5.difference()、difference_update()
print(set2,set3) set5 = set2.difference(set3) print(set5,set2) set3.difference_update(set2) print(set2,set3)
执行结果如下
{1, 2, 3, 4} {1, 2, 3, 5} {4} {1, 2, 3, 4} {1, 2, 3, 4} {5}
总结:difference()方法,是从本集合中删除和参数集合共同的元素并赋给一个集合,本集合和参数集合不变。difference_update()方法,是从本集合中删除和参数集合共同的元素,作用在本集合上。
6.discard()、remove()
共同点:
print(set3) set3.discard(2) print(set3) set3.remove(1) print(set3)
执行结果如下
{1, 2, 3, 5} {1, 3, 5} {3, 5}
不同点:
t1 = (1,1,1,2,3,5) set3 = set(t1) print(set3) set3.discard(6) print(set3) set.remove(6) print(set3)
执行结果如下
Traceback (most recent call last): File "/Users/liukai/PycharmProjects/s13/day3/blog.py", line 49, in <module> set.remove(6) TypeError: descriptor 'remove' requires a 'set' object but received a 'int' {1, 2, 3, 5} {1, 2, 3, 5}
总结:discard()、remove()方法都是删除一个元素,不同的是,discard()是有则删除,无则pass,而remove()方法是有则删除,无则异常,强烈建议使用discard()
7.intersection()、intersection_update()
print(set2,set3) set7 = set2.intersection(set3) print(set7)
执行结果如下
{1, 2, 3, 4} {1, 2, 3, 5}
{1, 2, 3}
总结:intersection()方法,返回一个本集合和参数集合的交集集合。
print(set2,set3) set2.intersection_update(set3) print(set2)
执行结果如下
{0, 1, 2, 3, 4} {1, 2, 3, 5}
{1, 2, 3}
总结:intersection_update()方法,返回一个本集合和参数集合的交集集合,作用于本集合。
8.update()
print(set2) set2.update({0,0,0,9}) print(set2)
执行结果如下
{1, 2, 3}
{0, 1, 2, 3, 9}
总结:update()方法直接更新一个集合到本集合并去重。
9.union()
print(set2,set3) print(set2.union(set3))
执行结果如下
{0, 1, 2, 3, 4} {1, 2, 3, 5}
{0, 1, 2, 3, 4, 5}
总结:union()方法返回本集合和参数集合的并集。
2.set应用举例分析
有两个字典,需要把新字典更新到老字典:
old_dict = { "#1":8, "#2":4, "#4":2, } new_dict = { "#1":4, "#2":4, "#3":2, }
解题思路:
1.需要求出老字典需要删除的条目。
2.需要求出新字典需要新增到老字典的条目。
3.需要求出新字典需要更新到老字典的条目。
解题方法:
###set(),把老字典的key转化成一个集合 old_key_set = set(old_dict.keys()) ###set(),把新字典的key转化成一个集合 new_key_set = set(new_dict.keys()) ###定义一个需要删除的集合,set的difference()求出在老字典的key而不在新字典的key的集合 remove_set = old_key_set.difference(new_key_set) ###删除老字典的条目 del old_dict["".join(list(remove_set))] ###定义一个需要新增的集合 update_set = new_key_set.difference(old_key_set) ###新增新字典的条目 old_dict["".join(list(update_set))] = new_dict["".join(list(update_set))] ###查找需要更新的key,我采取的方法是遍历两个字典 for i in old_dict: for j in new_dict: if i == j and old_dict[i] != new_dict[j]: old_dict[i] = new_dict[j] print(old_dict)
结果:
{'#1': 4, '#2': 4, '#3': 2}
3.set实战演练
目前工作经常有种需求,假如有两个IP文件,让查出相应的交集、差集、并集等。以下是临时写的代码,勿喷。。。
#!/usr/bin/env python3 # -*- coding=utf-8 -*- # Author : LiuKai import sys def file1_difference_file2(set1,set2): ret_set = set1.difference(set2) for i in ret_set: print(i) def file1_intersection_file2(set1,set2): res_set = set1.intersection(set2) for i in res_set: print(i) def file1_union_file2(set1,set2): res_set = set1.union(set2) for i in res_set: print(i) def main(): if len(sys.argv) != 3: print("用法:脚本名 文件1 文件2") sys.exit() file1_list = [] file2_list = [] with open("%s" % sys.argv[1],"r") as file1: for i in file1: file1_list.append(i.strip()) with open("%s" % sys.argv[2],"r") as file2: for j in file2: file2_list.append(j.strip()) file1_set = set(file1_list) file2_set = set(file2_list) user_input = input("<1,file1存在而file2不存在的>; <2,file1和file2的交集>; <3,file1和file2的并集> 请输入你要处理的方式 : ") user_input = int(user_input) if user_input == 1: file1_difference_file2(file1_set,file2_set) elif user_input == 2: file1_intersection_file2(file1_set,file2_set) elif user_input == 3: file1_union_file2(file1_set,file2_set) else: print("输入有误") sys.exit() main()
执行结果如下
liukai@bogon:~$ cat dd 1.1.1.1 1.2.2.2 1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4 5.5.5.5 liukai@bogon:~$ cat ff 1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4 liukai@bogon:~$ diffFile dd ff <1,file1存在而file2不存在的>; <2,file1和file2的交集>; <3,file1和file2的并集> 请输入你要处理的方式 : 1 5.5.5.5 1.2.2.2
2.函数
1.定义函数
def testfun(): print(123) return 111 print(456) fun=testfun() print(fun)
执行结果如下:
123 111
执行过程详解:
1.def testfun() 2.fun=testfun() 3.print(123) 4.return 111 5.fun=testfun() 6.print(fun)
总结:Python代码在文件中是从上到下执行,当函数遇到return时,结束函数体。所以456没有被打印。
2.函数参数
1.普通参数
def userInfo(user,passwd): print(user,passwd) userInfo("caesary","hello")
执行结果如下
caesary hello
2.默认参数
def userInfo(user,passwd,content="ok"): print(user,passwd,content) userInfo("caesary","hello") userInfo("caesary","hello",1234)
执行结果如下
caesary hello ok
caesary hello 1234
总结:默认参数必须放在参数列表最后。
3.可变参数
1.参数为元组
def testfun(*args): print(args) list1 = [1,2,3,4] testfun(list1) testfun(*list1)
执行结果如下
([1, 2, 3, 4],)
(1, 2, 3, 4)
总结:当函数参数为元组类可变参数时,调用函数的参数假如没有*,代表所有参数作为函数的第一个参数,调用函数的参数假如是*开头的,代表所有参数作为函数的相应所有参数。testfun(list1) -> list1 == *args ,输出为([1,2,3,4],);testfun(*list1) -> *list1 == *args -> list1 == args ,输出为(1,2,3,4)
2.参数为字典
def testfun(**kwargs): print(kwargs) dic1 = { "name":"caesary", "age" : 25 } testfun(**dic1) testfun(name="caesary",age=25)
执行结果如下
{'age': 25, 'name': 'caesary'} {'age': 25, 'name': 'caesary'}
总结:当函数的参数为字典类可变参数时,调用方式可以为(key1="value1",key2="value2")的方式,也可以把字典直接带入函数,不过要在字典前加**
4.万能参数
def testfun(*args,**kwargs): print(args,kwargs) dic1 = { "name":"caesary", "age" : 25 } list1 = [1,3,5] testfun(*list1,**dic1)
执行结果如下
(1, 3, 5) {'age': 25, 'name': 'caesary'}
总结:当参数既有元组类参数又有字典类参数时,顺序为先元组后字典。
3.全局变量
AGE = 25 def testfun(): AGE = 18 print(AGE) testfun() print(AGE)
执行结果如下
18 25
解析:AGE这个变量在函数外定义,为全局变量,当在函数体内重新赋值后,print的值为重新赋值后的值,然而并没有改变全局变量AGE,所以最后输出还是25。函数内定义的变量只作用于函数体内。想要改变函数外的全局变量,需要加global参数,如下所示:
AGE = 25 def testfun(): global AGE AGE = 18 print(AGE) testfun() print(AGE)
执行结果如下:
18 18
解析:虽然函数内不能改变全局变量的值,但是假如变量为列表、字典等,可以修改元素,但是不能删除重建。
Info = [1,2] dict_info = { "age":18, "name":"caesary", } def testfun(): Info.append(3) dict_info["addr"] = "HLJ" print(Info) print(dict_info) testfun() print(Info) print(dict_info)
执行结果如下
[1, 2, 3] {'age': 18, 'name': 'caesary', 'addr': 'HLJ'} [1, 2, 3] {'age': 18, 'name': 'caesary', 'addr': 'HLJ'}
4.函数FAQ
当两个相同函数名的函数,不同的函数体存在时的情况如下
def testfun(num1,num2): return num1 + num2 def testfun(num1,num2): return num1 * num2 print(testfun(3,4))
执行结果如下
12
解析:整块代码的执行顺序为
1.定义第一个testfun()函数,函数体为return num1 + num2 2.定义第二个testfun()同名函数,其实还是第一个函数,函数体指向return num1 * num2 3.执行testfun(3,4) 4.print输出
3.文件操作
1.open()
模式 | 描述 |
---|---|
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 |
r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 |
w | 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
w+ | 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
1.r模式
f = open("test.conf","r") print(f.read())
代码执行如下,内容是提前写好的。
ccccccccccccccccc
ddddddddddddddd
aaaaaaaaaaaaaaaaaaaaa
2.rb模式
f = open("test.conf","rb") print(f.read())
代码执行如下
b'ccccccccccccccccc ddddddddddddddd aaaaaaaaaaaaaaaaaaaaa'
总结:b是以二进制的模式打开文件。
3.r+模式
f = open("test.conf","r") print(f.read()) print("=========================================") f = open("test.conf","r+") f.write("eeeeee") f.close() f = open("test.conf","r") print(f.read())
执行结果如下
cccccccccccc ddddddddddddddd aaaaaaaaaaaaaaaaaaaaa ========================================= eeeeeecccccc ddddddddddddddd aaaaaaaaaaaaaaaaaaaaa
总结:可以看出,r+的写入模式是从文件开头开始写的,写入的内容会覆盖原来的内容。
4.w模式
f = open("test.conf","r") print(f.read()) print("=========================================") f = open("test.conf","w") f.write("eeeeee") f.close() f = open("test.conf","r") print(f.read())
执行结果如下
eeeeeecccccc ddddddddddddddd aaaaaaaaaaaaaaaaaaaaa ========================================= eeeeee
总结:w模式,会把源文件清空,并重新写入。
5.a模式
f = open("test.conf","r") print(f.read()) print("=========================================") f = open("test.conf","a") f.write("ffffff ") f.close() f = open("test.conf","r") print(f.read())
执行结果如下
eeeeee ========================================= eeeeeeffffff
总结:a模式,会把写入的内容追加到源文件的末尾。
2.read()、readline()、readlines()
1.read()
f = open("test.conf","r") print(f.read())
执行结果如下
aaaaaaaaa
ooooooooo
eeeeeeeee
fffffffff
总结:read()方法是把整个文件以字符串的形式输出。
2.readline()
f = open("test.conf","r") print(f.readline())
执行结果如下
aaaaaaaaa
总结:readline()方法只是读取一行文件。
3.readlines()
f = open("test.conf","r") print(f.readlines())
执行结果如下
['aaaaaaaaa ', 'ooooooooo ', 'eeeeeeeee ', 'fffffffff ']
总结:readlines()方法,会把整个文件按行以列表的形式输出,比较常用。
3.tell()、seek()
1.tell()
f = open("test.conf","r") print(f.readline(),f.tell())
执行结果如下
aaaaaaaaa
10
总结:readline()方法是读取一行文件,tell()方法会输出当前文件的指针位置。
2.seek()
f = open("test.conf","r") print(f.readline(),f.tell()) f.seek(0) print(f.tell())
执行结果如下
aaaaaaaaa 10 0
总结:seek()方法可以设置文件的位置偏移,如例子当偏移到0这个位置后,tell()方法输出当前指针位置为0.