集合、文件读写、函数
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)

浙公网安备 33010602011771号