python第三周:集合、函数、编码、文件
1.集合:
集合的创建:
list_1 = set([1,2,3,4,5])
list_2 = set([2,3,44,7,8])
集合的特性:集合是无序的,集合可以去掉重复的元素
集合的操作:
求交集:
print(list_1.intersection(list_2)) #{2,3} print(list_l & list_2) #求交集,{2,3}
求并集:
print(list_1.union(list_2)) #{1,2,3,4,5,7,8,44} print(list_l | list_2) #求并集,{1,2,3,4,5,7,8,44}
求差集:
print(list_1.defference(list_2)) #in list_1 but not in list_2,{1,4,5} print(list_l - list_2) #求差集,in list_1 but not in list_2:{1,4,5}
判断子集:
print(list_1.issubset(list_2)) #list_1是否是list_2的子集,None
判断父集:
print(list_1.issuperset(list_2)) #list_1是否是list_2的父集,None
对称差集:
print(list_l.symmetric_difference(list_2)) #对称差集,并集里面去掉交集,{1,4,5,7,8,44}
print(list_l ^ list_2) #对称差集,并集里面去掉交集
判断交集:
print(lsit_1.isdijoint(list_2)) #Yes
增加:
lsit_3 = set([1,2,3,4]) #单个增加: list_3.add(5) #多个增加: list_3.update([6,7,8,9])
删除:
删除:list_3.remove(1) print(list_3.pop()) #随机删除
求集合的长度:
print(len(list_3))
2.文件
文件的创建:
f = open("yesterday","w",encoding="utf-8") ''' #with语句,为了避免打开文件后忘记关闭,可以通过管理上下文,即: with open("log","r") as f: pass #python2.7之后,with有支持同时对多个文件的上下文进行管理,即: with open("log1") as obj1,open("log2") as obj2: psss ''' #开发规范:一行不得超过八十个字符 with open("yesterday2","r",encoding="GB18030") as f,\ open("yesterday","r",encoding="GB18030") as f2: for line in f: print(line.strip())
文件的操作:
读:
f = open("yesterday","r",encoding="utf-8")#不可写 data = f.read() print(data) #输出文件的内容 list = f.readlines() ''' #将硬盘中的数据全部读入内存中形成一个列表,并且自动添加了换行符. ['我爱北京天安门,\n', '天安门上太阳升\n', '我爱北京天安门\n'] ''' print(f.readline()) #一行一行地读 #循环读: for line in f: print(line)
写:
f = open("yesterday","w",encoding="utf-8") #不可读,每运行一次就会创建一个新的文件覆盖掉原来的文件 f.write("sladjla")
追加:
f = open("yesterday","a",encoding="utf-8")#不可读 f.write("sldad")
句柄位置操作:
print(f.tell()) #打印句柄位置 f.seek(5) #使句柄回到某个位置 print(f.encoding) #打印文件的编码 print(f.fileno()) #返回文件编号 print(f.name) #打印文件名字 print(f.isatty()) #判断是否为终端设备 True、False print(f.seekable()) #判断句柄是否可移 True、False print(f.readable()) #判断文件是否可读 True、False
刷新:
f.flush()#刷新,将内存中的内容一次性刷入硬盘中 import sys,time for i in range(50): sys.stdout.write("#") sys.stdout.flush() time.sleep(0.1)
读写、写读、追加的、二进制读写:
f = open("yesterday2","r+",encoding="GB18030")#读写模式,不会清空原文件 f = open("yesterday2","w+",encoding="GB18030")#写读模式,会清空原文件 f = open("yesterday2","a+",encoding = "GB18030")#追加读 f = open("yesterday2","rb或者wb") #二进制文件 print(f.readline()) print(f.readline()) print(f.readline()) print(f.tell()) f.write("\n------diao------") #只能添加在末尾 print(f.readline()) #文件操作的二进制读写 f = open("yesterday2","rb") print(f.readline())#b'\r\n' f = open("yesterday2","wb") f.write("hello binary".encode())#只能写入二进制格式 ''' "U"表示在读取时,可以将\r \n \r\n自动转换为\n(与r或r+模式同时使用) > rU > r+U '''
文件修改:
f = open("yesterday","r",encoding="GB18030") f_new = open("yesterday3","w",encoding="GB18030") for line in f: if "poj" in line: line = line.replace("poj","急急急急急急") f_new.write(line) f.close() f_new.close()
3.字符编码与转换:
GBK--decode-->unicode【中间站】--encode-->utf-8
utf-8--decode-->unicode【中间站】--encode-->GBk
GBK转换为utf-8流程:
1.首先通过编码【decode】转换为Unicode编码
2.然后通过解码【encode】转换为utf-8编码
utf-8转换为GBK流程:
1.首先通过编码【decode】转换为Unicode编码
2.然后通过解码【encode】转换为utf-8编码
utf-8是Unicode编码的扩展集,故在utf-8程序中,Unicode格式可以直接打印
但是GBK编码不能在Unicode程序中直接打印,即使Unicode兼容GBK编码
在python2中解释器默认是ASCII码
python3中解释器默认是unicode编码
在python3中进行转码、编码会自动转成二进制类型
![](https://img2018.cnblogs.com/blog/1478184/201811/1478184-20181115215240960-948901550.png)
s = "你好" s_gbk = s.encode("gbk") print(s_gbk)#b'\xc4\xe3\xba\xc3' print(s.encode())#b'\xe4\xbd\xa0\xe5\xa5\xbd' gbk_to_utf8 = s_gbk.decode("gbk").encode("utf-8") print(gbk_to_utf8)#b'\xe4\xbd\xa0\xe5\xa5\xbd' s = "你哈" print(s.encode("gbk")) #b'\xc4\xe3\xb9\xfe',因为解释器默认是Unicode编码 print(s.encode("utf-8")) #b'\xe4\xbd\xa0\xe5\x93\x88' print(s.encode("utf- 8").decode("utf8").encode("gb2312").decode("gb2312"))#你哈
4.函数与函数式编程:
编程方法:
1.面向对象
2.面向过程
3.函数式编程
函数定义:
函数式逻辑结构化和过化的一种编程方法
python中函数定义的方法:
def text(x): "The function definition" x += 1 return x '''' def:定义函数中的关键字 text:函数名 ():内可定义形参 "":文档描述(非必要,但是强烈建议为你的函数添加描述信息) x += 1:泛指代码或程序处理器 return:定义返回值 ''''
使用函数的优点:
1.避免了大量代码的重复使用
2.保持一致性:修改函数中的代码,在所有使用函数的地方都会改变
3.可扩展性(一致性)
import time def logger(): time_format = "%Y=%m-%d %X" time_current = time.strftime(time_format) with open("hahaha","a+",encoding="utf-8") as f: f.write("%send action\n"%time_current) def text1(): print("in the tex1") logger() def text2(): print("in the tex2") logger() def text3(): print("in the tex3") logger() text1() text2() text3()
函数和过程:
过程定义:过程就是简单没有返回值的函数
总结:一个函数/过程没有使用return显性的定义返回值时,python解释器会隐式返回None,所以在python中即便是过程也可以算作是函数
#函数: def func1(): "testing1" print("in the func1") return 0 #过程: def func2(): "testing2" print("in the func2") x = func1() print("from func1 return is %s "%x) #from func1 return is 0 y = func2() print("from func2 return is %s"%y) #from func2 return is None #当一个函数/过程没有使用return显性的定义返回值时,python解释器会隐式返回None, #所以在python中即便是过程也可以算作函数
函数返回值:
返回值数=0,返回None
返回值数=1,返回object
返回值数>1,返回tuple
def text1(): print("in the text1") ''' return 0 #结束函数,并返回一个值 print("text end") #不会执行 ''' def text2(): print("in the text2") return 0 def text3(): print("in the text3") return 1,"hello",["alex","wupeiqi"],{"name":"alex"} x = text1() y = text2() z = text3() print(type(x),x) #<class 'NoneType'> None print(type(y),y) #<class 'int'> 0 print(type(z),z) #<class 'tuple'> (1, 'hello', ['alex', 'wupeiqi'], {'name': 'alex'})
函数调用:test()执行,()表示调用test,()可以有参数也可以没有
参数:
1.形参和实参:
形参:形式参数,不是实际存在的,是虚拟变量。在定义函数和函数体的时候使用形参,目的是在函数调用时接受实参(实参个数、类型因该与形参一一对应)
实参:实际参数,调用函数时传给函数的参数,可以是常量、变量、表达式、函数传给形参
区别:形参时虚拟的,不占用内存空间,形参变量只有在被调用时才分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参
2.位置参数和关键字参数(标准调用:实参和形参位置一一对应;关键字调用:位置无需固定)
#标准调用,实参与形参一一对应 def test1(x,y): "x、y是位置参数" print("in the test1:") print("x = %s\ny = %s"%(x,y)) test1(2,1) #实参跟形参必须一一对应 #关键字调用,与形参顺序无关 def test2(x,y): print("in the test2:") print("x = %s\ny = %s"%(x,y)) test2(y = 1,x = 2) #test2(x = 2,3) error #test2(3,y = 2) OK #因此关键字参数不能位于位置参数的前面
3.默认参数:特点:调用函数的时候,默认参数非必须传递
def test(x,y=2): print(x) print(y) test(x = 1,y = 3) #OK test(1) #OK #test(y = 3) error #特点:调用函数的时候,默认参数非必须传递
4.参数组
def test(*args): print(args) test(1,2,3,4,5) #(1, 2, 3, 4, 5) test(*[1,2,3,5,5]) #args = tuple([1,2,3,5,5]):(1, 2, 3, 5, 5) def test1(x,*args): print(x) print(args) test1(1,2,3,4,5,6,34,3) #1 #*args是接收N个位置参数,转换成元组的方式 (2, 3, 4, 5, 6, 34, 3) #**kwargs:是就收N个关键字参数,转换成字典的方式;传递字典 def test2(**kwargs): print(kwargs) test2(name = "alex",age = 22,sex = "N") #{'name': 'alex', 'age': 22, 'sex': 'N'} def test3(name,*args,**kwargs): print("the information of %s:"%name) print(kwargs) print("%s like the numbers:%s"%(name,args)) test3("alex",3,7,21,age = 19,sex = "m") #def test4(name,**kwargs,age=18) error,默认参数必须放在参数组的前面 #def test4(name,age=18,**kwargs) OK
注意:1.关键字参数必须位于位置参数的后面 2.默认参数必须放在参数组的前面
前向引用:
函数action体内嵌套某一函数logger,该logger的声明必须早于action函数的调用,否则报错
全局变量与局部变量:
在子程序中定义的变量称为局部变量,在程序一开始定义的变量称为全局变量。
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序
当全局变量与局部变量冲突时:
在定义局部变量的子程序内,局部变量会屏蔽掉全局变量,在其他地方全部变量起作用
school = "Oldboy edu" #全局变量 def change_name(name): "这个函数就是其内部即局部变量的作用域" global school #将school改为全局变量 school = "mage linux" print("school:",school) print("before change:",name) name = "Alex li" print("after change:",name) name = "alex" change_name(name) print(name)#alex print("shcool:",school)#shcool: mage linux #一般来说,我们不应该在函数内部将局部变量改为全局变量 因为这样在无数次调用这个函数后,我们很难知道实在哪儿将变量修改了 故我们不应该使用这种方法: def change_name(): global name name = "alex" change_name() print(name) #附注:列表、字典是可以在函数中修改的
高阶函数:
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就叫高阶函数
def abs(x): if x>=0: return x else: return -x def add(a,b,f): return f(a)+f(b) print(add(3,-6,abs)) #9
递归:
定义:如果一个函数在内部调用自己本身,这个函数就是递归函数
特性:
1.必须有一个明确的结束条件
2.每次进入更深一层循环时,问题规模相比上次递归有所减少
3.递归效率不高,递归层次过多时回导致栈溢出
def cal(n):
print(n) if int(n/2)>0: return cal(int(n/2)) print("---->",n) cal(10)