集合、文件读写、函数
1 Set 方法
Python 拥有一套能够在集合(set)上使用的内建方法。
方法 | 描述 |
---|---|
向集合添加元素。 | |
删除集合中的所有元素。 | |
返回集合的副本。 | |
返回包含两个或更多集合之间差异的集合。 | |
删除此集合中也包含在另一个指定集合中的项目。 | |
删除指定项目。 | |
返回为两个其他集合的交集的集合。 | |
删除此集合中不存在于其他指定集合中的项目。 | |
返回两个集合是否有交集。 | |
返回另一个集合是否包含此集合。 | |
返回此集合是否包含另一个集合。 | |
从集合中删除一个元素。 | |
删除指定元素。 | |
返回具有两组集合的对称差集的集合。 | |
插入此集合和另一个集合的对称差集。 | |
返回包含集合并集的集合。 | |
用此集合和其他集合的并集来更新集合。 |
集合(Set)
集合是无序和无索引的集合。在 Python 中,集合用花括号编写。
intersection() 交集
union() 并集
difference() 差集
issubset() 子集
issuperset() 父集
symmetric_difference() 对称差集
isdisjoint() 判断是否有差集
2 关系操作
list_1 = [1,4,5,7,3,6,7,9] list_1 = set(list_1) list_2 = set([2,6,0,66,22,8,8,4]) # print(list_1,list_2) # 交集 print(list_1.intersection(list_2)) # 并集 print(list_1.union(list_2)) # 差集 print(list_1.difference(list_2)) print(list_2.difference(list_1)) # 子集 # issubset(),返回另一个集合是否包含此集合。 # issuperset(),返回此集合是否包含另一个集合。 list_3 = set([1,3,7]) print(list_3.issubset(list_1)) # 此集合是否为另一个集合的子集合 print(list_1.issuperset(list_3)) # 此集合是否为另一个集合的父集合 # 对称差集(合并没有交集) print(list_1.symmetric_difference(list_2)) print("---------------") # isdisjoint()返回两个集合是否有交集。 list_4 = set([5,6,7,8]) print(list_3.isdisjoint(list_4))
3 关系运算符:
# 交集 print(list_1 & list_2) # union print(list_2 | list_1) #difference print(list_1 - list_2) # in list_1 not in list_2 #对称差集 print(list_1 ^ list_2)
4 基本操作
list_1 = [1,4,5,7,3,6,7,9] list_1 = set(list_1) #添加 list_1.add("hello") #添加一项 list_1.update(["hi","word"]) #添加多项,不加中括号变成'w','i', 'o', 'd', 'h', 'r' #获取长度 long = len(list_1) print(list_1,"\t",long) #judge判断 print("hello" in list_1) #判断是否存在集合里 print("hello" not in list_1) #判断是否不在集合里 #copy list_1_copy = list_1.copy() print(list_1,list_1_copy) #delete print(list_1.pop()) list_1.remove("haha") # 删除不存在元素会报错 list_1.discard("haha") #删除不存在元素不会报错 print(list_1) #clear list_1.clear()
Python 有一组可用于文件对象的方法。
方法 | 描述 |
---|---|
关闭文件。 | |
detach() | 从缓冲区返回分离的原始流(raw stream)。 |
从操作系统的角度返回表示流的数字。 | |
刷新内部缓冲区。 | |
返回文件流是否是交互式的。 | |
返回文件内容。 | |
返回是否能够读取文件流。 | |
返回文件中的一行。 | |
返回文件中的行列表。 | |
更改文件位置。 | |
返回文件是否允许我们更改文件位置。 | |
返回当前的文件位置。 | |
把文件调整为指定的大小。 | |
返回是否能够写入文件。 | |
把指定的字符串写入文件。 | |
把字符串列表写入文件。 |
read()、readline()、readlines()
我们谈到“文本处理”时,我们通常是指处理的内容。Python 将文本文件的内容读入可以操作的字符串变量非常容易。文件对象提供了三个“读”方法: .read()、.readline() 和 .readlines()。每种方法可以接受一个变量以限制每次读取的数据量,但它们通常不使用变量。 .read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。然而 .read() 生成文件内容最直接的字符串表示,但对于连续的面向行的处理,它却是不必要的,并且如果文件大于可用内存,则不可能实现这种处理。
.readline() 和 .readlines() 非常相似。它们都在类似于以下的结构中使用:
Python .readlines() 示例
fh = open( 'c:\autoexec.bat') for line in fh.readlines(): print line.readline() 和 .readlines()之间的差异是后者一次读取整个文件,象 .read()一样。.readlines()自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for... in ... 结构进行处理。另一方面,.readline()每次只读取一行,通常比 .readlines()慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用.readline()。
写:
writeline()是输出后换行,下次写会在下一行写。write()是输出后光标在行末不会换行,下次写会接着这行写
通过readline输出,对于比较大的文件,这种占用内存比较小。 #coding:utf-8 f = open('poem.txt','r') result = list() for line in open('poem.txt'): line = f.readline() print line result.append(line) print result f.close() open('result-readline.txt', 'w').write('%s' % '\n'.join(result))
#coding:utf-8 '''cdays-4-exercise-6.py 文件基本操作 @note: 文件读取写入, 列表排序, 字符串操作 @see: 字符串各方法可参考hekp(str)或Python在线文档http://docs.python.org/lib/string-methods.html ''' f = open('cdays-4-test.txt', 'r') #以读方式打开文件 result = list() for line in f.readlines(): #依次读取每行 line = line.strip() #去掉每行头尾空白 if not len(line) or line.startswith('#'): #判断是否是空行或注释行 continue #是的话,跳过不处理 result.append(line) #保存 result.sort() #排序结果 print result open('cdays-4-result.txt', 'w').write('%s' % '\n'.join(result)) #保存入结果文件
文件读与写
#data = open("yesterday",'r',encoding="utf-8").read() #r 只读,如果连续读两次文件,第二次就不能读到内容(因为第一次读完,光标在最后) """ f = open("yesterday2",'r',encoding="utf-8") data = f.read() data2 = f.read() print(data) print("-------data2----------%s---" %data2) """ #w 创建覆盖(原有)文件 #a = append 追加 # w,a 不能读 f = open("yesterday2",'a',encoding="utf-8") #文件句柄 f.write("\nwhen i was young i listen to the radio\n") data = f.read() print('----read--------',data) f.close()
文件读与写二
f = open("yesterday",'r',encoding="utf-8") count =0 for line in f: if count == 9: print('-------分割线-------') count += 1 print(line) count += 1 """ for index,line in enumerate(f.readlnes()): if index == 9: print('------分割线-------') continue print(line.strip()) """ # for i in range(5): # print(f.readline())
文件读与写三
1 方法
f = open("yesterday",'r',encoding="utf-8") # 文件句柄 print(f.tell()) #返回当前的文件位置。 print(f.readline()) print(f.tell()) print(f.seek(0)) #更改文件位置。 print(f.seekable()) #返回文件是否允许我们更改文件位置。 print(f.encoding) #打印文件编码 print(f.fileno()) #从操作系统的角度返回表示流的数字。 #detach() #编辑过程中修改字符编码 print(f.name) print(f.isatty()) #返回文件流是否是交互式的。检查文件是否已连接到终端设备: print(f.readable()) # 是否可读 print(f.writable()) # 是否可写 print(f.closed) # 判断文件是否关闭 # print(f.newlines)
f = open("yesterday",'a',encoding="utf-8") # 文件句柄 # print(f.seek(0)) f.seek(10) # 使用seek()无效 f.truncate(30) f.close()
read()读取剩下的所有内容,文件大时不要用
2 打开文件模式
打开文件的模式有:
-
r,只读模式(默认)。
-
w,只写模式。【不可读;不存在则创建;存在则删除内容;】
-
a,追加模式。【可读; 不存在则创建;存在则只追加内容;】
"+" 表示可以同时读写某个文件
-
r+,可读写文件。【可读;可写;可追加】
-
w+,写读
-
a+,同a
"U"表示在读取时,可以将 \r \n \r\n自动转换成 \n (与 r 或 r+ 模式同使用)
-
rU
-
r+U
"b"表示处理二进制文件(如:FTP发送上传ISO镜像文件,linux可忽略,windows处理二进制文件时需标注)
-
rb
-
wb
-
ab
3 flush()
刷新内部缓冲区。
一:
cmd执行: >d: >python >>> f = open("test.text","w") >>> f.write("hello1\n") 7 >>> f.flush() # 刷新缓存区后再打开文件显示一行内容 >>> f.write("hello2\n") 7 >>> f.flush() # 再刷新显示一行
二:
import sys,time for i in range(20): sys.stdout.write("#") sys.stdout.flush() time.sleep(0.1)
4 r+、w+、a+
# f = open("yesterday2",'r+',encoding="utf-8") # 文件句柄 读写 # print(f.readline()) # print(f.tell()) # num = f.tell() # f.write("--------你好------------") #会写在最后 # print(f.seek(num)) #写入后光标会跳到最后 # print(f.readline()) f = open("yesterday",'w+',encoding="utf-8") # 文件句柄 写读(覆盖原文件) # f = open("yesterday",'a+',encoding="utf-8") # 文件句柄 追加读写 f.write("----------hello--------\n") f.write("----------hello--------\n") print(f.tell()) f.seek(10) print(f.tell()) print(f.readline()) f.write("-------------hi--------") f.close()
5 二进制rb、wb、ab
f = open("yesterday",'rb') # 文件句柄 二进制文件 # 网络传输用到 print(f.readline()) print(f.readline()) f = open("yesterday",'wb') #f = open("yesterday",'ab') f.write("--hello word--\n".encode()) f.write("--hello word--\n".encode())
文件修改
1
f = open("yesterday2","r",encoding="utf-8") f_new = open("yesterday2.bak","w",encoding="utf-8") print(f.tell(),f_new.tell()) for line in f: if "昨日当我年少轻狂" in line: line = line.replace("昨日当我年少轻狂","昨日当阿福年少轻狂") f_new.write(line) print(line.strip()) f.close() f_new.close()
with
为了避免打开文件后忘记关闭,可以通过管理上下文,
如此方式,当with代码块执行完毕时,内部会自动关闭并释放文件资源。
在Python 2.7 后,with又支持同时对多个文件的上下文进行管理
# f = open("yesterday2","r",encoding="utf-8") with open("yesterday2","r",encoding="utf-8") as f,\ open("yesterday2","r",encoding="utf-8") as f2: for line in f: print(line.strip()) print("-------------") for line2 in f2: print(line2.strip())
程序练习
1 实现简单的shell sed替换功能
import sys find_str = sys.argv[1] replace_str = sys.argv[2] f = open("yesterday2","r",encoding="utf-8") f_new = open("yesterday2.bak","w",encoding="utf-8") print(f.tell(),f_new.tell()) for line in f: if find_str in line: line = line.replace(find_str,replace_str) f_new.write(line) f.close() f_new.close()
2 修改haproxy配置文件
用到函数:
arg = """{ 'bakend': 'www.oldboy.org', 'record': { 'server': '100.1.7.9', 'weight': 20, 'maxconn': 30 } }""" arg = eval(arg) print(arg,type(arg))
需求:
1、查 输入:www.oldboy.org 获取当前backend下的所有记录 2、新建 输入: arg = { 'bakend': 'www.oldboy.org', 'record':{ 'server': '100.1.7.9', 'weight': 20, 'maxconn': 30 } } 3、删除 输入: arg = { 'bakend': 'www.oldboy.org', 'record':{ 'server': '100.1.7.9', 'weight': 20, 'maxconn': 30 } }
原配置文件:
eval()
global log 127.0.0.1 local2 daemon maxconn 256 log 127.0.0.1 local2 info defaults log global mode http timeout connect 5000ms timeout client 50000ms timeout server 50000ms option dontlognull listen stats :8888 stats enable stats uri /admin stats auth admin:1234 frontend oldboy.org bind 0.0.0.0:80 option httplog option httpclose option forwardfor log global acl www hdr_reg(host) -i www.oldboy.org use_backend www.oldboy.org if www backend www.oldboy.org server 100.1.7.9 100.1.7.9 weight 20 maxconn 3000
字符编码与转码
ASSCI英文及符号占1个字节;unicode占2个字节;utf-8英文字符按ASCII码形式存储,中文占3个字节。
1 python2.x下:
#-*- coding:utf-8 -*- import sys print(sys.getdefaultencoding()) s = "你好" # utf-8 --> gbk 编码成(需指定编码)unicode再解码成gbk s_to_unicode = s.decode("utf-8") print(s_to_unicode) s_to_gbk = s_to_unicode.encode("gbk") print(s_to_gbk) # gbk --> utf-8 gbk_to_utf8 = s_to_gbk.decode("gbk").encode("utf-8") print(gbk_to_utf8) #输出内容 # assci # 你好 # (乱码) # 你好 #------------------------------------- s2 = u"你好" # 现在是unicode print(s) # unicode 与 utf-8 之间可以直接打印 s_to_gbk = s.encode("gbk") print(s_to_gbk) # gbk --> utf-8 gbk_to_utf8 = s_to_gbk.decode("gbk").encode("utf-8") print(gbk_to_utf8)
2 python3.x:
decode:编码成字符串
encode:解码成对应字符编码的二进制
#-*- coding:gbk -*- #这里为文件字符编码,变量s还是unicode s = "你好" print(s) s_gbk = s.encode("gbk") print(s_gbk) #默认就是unicode,不用decode print(s.encode()) gbk_to_utf8 = s_gbk.decode("gbk").encode("utf-8") print("utf-8",gbk_to_utf8) utf8_to_gbk = gbk_to_utf8.decode("utf-8").encode("gbk") print("gbk",utf8_to_gbk) #-------------- print(s) print(s.encode("gbk")) print(s.encode("ut")) print(s.encode("utf-8").decode("utf-8").encode("gbk2312").decode("gbk2312"))
函数与函数式编程
函数
-
面向对象:——————》 类——————》 class
-
面向过程:——————》 过程————》 def
-
函数式编程:————》 函数————》 def
初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变量,y是x的函数。自变量x的取值范围叫做这个函数的定义域。如:y=2x 编程语言中函数定义:函数是逻辑结构化和过程过得一种编程方法。
#python中函数的定义方法: def test(x): "The function definitions" x += 1 return x # def:定义函数的关键字 # test:函数名 # ():内可定义形参 # "":文件描述(非必要,但是强烈建议为你的函数添加描述信息) # x += 1:泛指代码块或程序处理逻辑 # return:定义返回值
ps:函数式编程就是:先定义一个数学函数,然后按照这个数字模型用编程语言去实现它。
# 函数 def func1(): "testing1" print('in the func1') return 0 # 过程 def func2(): "testing2" print('in the func2') x=func1() y=func2() print(x,y)
return返回值
def test1(): print("this is test1") def test2(): print("this is test2") return 0 def test3(): print("this is test3") return 1,["zhangsan,lisi"],{"ar fu":"ar gui"} t1 = test1() t2 = test2() t3 = test3() print(t1) print(t2) print(t3) # this is test1 # this is test2 # this is test3 # None # 0 # (1, ['zhangsan,lisi'], {'ar fu': 'ar gui'})
1 日志加上时间
import time def logger(): time_format = '%Y-%m-%d %X' time_current = time.strftime(time_format) with open("yesterday","a+",encoding="utf-8") as f: f.write("%s end action\n" %time_current) def test1(): print("this is test1") logger() def test2(): print("this is test2") logger() test1() test2()
概括使用函数的三大优点
-
代码复用
-
保持一致性
-
可扩展性
2 函数调用
调用方法:test()执行,()表示调用函数test,()内可以有函数也可以没有
参数:
1.形参和实参
形参:形式参数,不是实际存在,是虚拟变量。在定义函数和函数体的时候使用参数,目的是在函数调用时接收实参。
形参排放顺序:普通形参 -->*args --> 默认参数 -->***kwargs
ps:若默认参数放在*args前,会发生默认参数有多个值而报错
实参:实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给参数
区别:形参是虚拟的,不占用内存空间,形参变量只有在被调用时才可分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参。
2.位置参数和关键字
(标准调用:实参与形参位置一一对应;关键字调用:位置无固定)且关键字一定要在位置参数后面。
# 位置参数与关键字 def test(x,y,z): #形参 print(x) print(y) print(z) # test(y=2,x=1) #关键字,与形参顺序无关 # test(1,2) #位置参数,实参与形参一一对应 test(5,y=2,z=4) # 先位置参数,再接关键字(到最后且不使用前面的形参)
3.默认参数(给形参赋予一个初始值)
# 默认参数 def test(x,y=2): print(x,y) # print(y) def conn(host,port=3306): # print(host) pass test(1,3) conn(1)
#默认参数特点:调用函数的时候,默认参数非必须传递 #用途:1.默认安装值 2.默认值
4.参数组
def test(x,y,z=2): # 默认参数外,实参处必须写够位置参数个数 print(x,y,z) test(1,4)
*args
def test(*args,age=18): #接收N个参数且转换成元组的形式 print(args) print(age) test(age=12,*[1,2,3,4]) test(*[1,2,4,5,5]) #args=tuple([1,2,4,5,5]) # *args:接收N个位置参数,转换成元组形式,或*[234,234] def test(x,*args): print(x) print(args) test(1,234,234,123) test(1,*[234,234,123]) test(1) #输出的args为空元组
**kwargs
def test2(**kwargs): # **kwargs:把N个关键字参数装换成字典方式,或**{'name':'zhangsan','age':8} print(kwargs) print(kwargs['name']) print(kwargs['age']) test2(name='zhangsan',age=8,sex='N') test2(**{'name':'zhangsan','age':8})
*args和**kwargs
形参排放顺序:普通形参 --> *args --> 默认参数 -->**kwargs
def test4(name,*args,age=18,**kwargs): #**kwargs(为关键字参数)必须放最后 print(name) print(age) print(args) print(kwargs) test4('zhangsan','hello','hi',sex='m',hobby='tesla')
局部变量
函数内的变量为局部变量。global声明可以变成全局(不建议用)
musci = "最炫民族风" def change_name(name): global music #函数内声明全局变量 music = "荷塘月色" print("before change: ",name,music) name = "ar fu" #这个函数就是这个变量的作用域 print("after change: ",name,music) name = "zhang san" change_name(name) print(name) print(music) # before change: zhang san 荷塘月色 # after change: ar fu 荷塘月色 # zhang san # 荷塘月色
函数内可以修改的外部的数据类型
#函数内可以修改外面全局的列表、字典、集合、类。不能改字符串和数字
school = "hello" names = ["zhangsan","lisi","wangwu"] def change_name(): names[0] = "赵六" school = "hi" print("inside func",names,school) change_name() print(names,school)
全局与局部变量
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
当全局变量与局部变量同名时:
在定义局部变量的子程序内,局部变量起作用,在其他地方全局变量起作用。
递归
在函数内部,可以调用其他函数。如果一个函数在内部调用自身,这个函数就是递归函数。
递归特性:
-
必须有一个明确的结束条件
-
每次进入更深一次递归是,问题规模相比上次递归都应有所减少
-
递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈会加一层栈帧,每当函数返回,栈帧就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
def calc(n): print(n) if int(n/2) > 0: return calc(int(n/2)) print("--> ",n) calc(10)
匿名函数 lambda
匿名函数就是不需要显式的指定函数
def calc(n): return n**n print(calc(10)) # 换成匿名函数 calc = lambda n:n**n print(calc(10))
匿名函数主要是和其他函数搭配使用
res = map(lambda x:x**2,[1,5,7,4,8]) print(type(res)) for i in res: print(i)
<class 'map'>
1
25
49
16
64
函数式编程介绍
函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。
函数式编程中的函数这个术语不是指计算机中的函数(实际上是Subroutine),而是指数学中的函数,即自变量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态。比如sqrt(x)函数计算x的平方根,只要x不变,不论什么时候调用,调用几次,值都是不变的。
Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
一、定义
简单说,"函数式编程"是一种
主要思想是把运算过程尽量写成一系列嵌套的函数调用。举例来说,现在有这样一个数学表达式:
(1 + 2) * 3 - 4
传统的过程式编程,可能这样写:
var a = 1 + 2;
var b = a * 3;
var c = b - 4;
函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,然后写成下面这样:
var result = subtract(multiply(add(1,2), 3), 4);
这段代码再演进以下,可以变成这样
add(1,2).multiply(3).subtract(4)
这基本就是自然语言的表达了。再看下面的代码,大家应该一眼就能明白它的意思吧:
merge([1,2],[3,4]).sort().search("2")
因此,函数式编程的代码更容易理解。
要想学好函数式编程,不要玩py,玩Erlang,Haskell, 好了,我只会这么多了。。。
高阶函数
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数称为高阶函数。
def add(x,y,f): return f(x)+f(y) res = add(5,-10,abs) #abs:绝对值 print(res)