python学习笔记3--集合、文件操作、字符编码转换、函数
一、集合
1、定义:集合使用{}定义,集合是一组无序不重复的数据组合,主要用于数据去重和关系测试
list_1 = [1,2,3,4,5] list_2 = [2,4,5,6,7,6] # 构建集合s1、s2 s1 = set(list_1) s2 = set(list_2) # 打印集合 print("集合s1:",s1) print("集合s2:",s2) 输出结果: 集合s1: {1, 2, 3, 4, 5} 集合s2: {2, 4, 5, 6, 7}
2、关系测试:
# 取交集 print("取交集:\ns1 & s2:",s1 & s2) 输出结果: 取交集: s1 & s2: {2, 4, 5} # 取并集 print("取并集:\ns1 | s2:",s1 | s2) 输出结果: 取并集: s1 | s2: {1, 2, 3, 4, 5, 6, 7} # 取差集 print("取差集:\ns1 - s2:",s1 - s2) print("s2 - s1:",s2 - s1) 输出结果: 取差集: s1 - s2: {1, 3} s2 - s1: {6, 7} # 取对称差集 print("取对称差集:\ns1 ^ s2:",s1 ^ s2) 输出结果: 取对称差集: s1 ^ s2: {1, 3, 6, 7}
3、集合方法:
s1.intersection(s2):取s1和s2的交集
s1.union(s2):取s1和s2的并集
s1.difference(s2):取s1和s2的差集,等价于s1 - s2
s1.issubset(s2):判断s1是否是s2的子集
s1.issuperset(s2):判断s1是否是s2的父集
s1.symmetric_difference(s2):取s1和s2的对称差集
s1.isdisjoint(s2):判断s1和s2是否有交集
s1.add('a'):在s1中新增一个元素
s1.update([9,7,99]):在s1中新增多个元素
s1.remove('a'):在s1中删除项a,如果该项不存在则报错
s1.pop():在s1中随机删除一个元素并返回删除的这个元素
s1.discard():删除一项但不反回删除的项,如果该项不存在也不报错
二、文件操作
1、文件操作流程
打开文件——>操作文件——>关闭文件
2、打开文件
open("文件名",["模式"],["字符编码"])返回文件句柄,默认使用系统的字符编码且以只读模式打开
3、模式:
r:只读模式打开
w:以写模式打开文件,如果该文件不存在,则会新建文件,如果该文件存在,则会覆盖,写的内容会写在同一行之中
a:追加模式打开,不可读
r+:读和追加的模式打开文件,写文件会写到文件末尾
w+:写读模式,先创建一个新文件,然后再写入该文件
a+:可读追加
rb:以二进制格式读取文件,二进制文件不可以传入encoding参数
4、文件方法
f.read([size]):默认读取文件的所有行,指定size则读取size个字符
f.readline():一行一行读取文件内容
f.readlines():将所有行读出并存放到一个列表中,每一行是一个元素,此方法只适合读取小文件
f.tell():返回当前光标在文件中的位置,tell靠字符个数来计数
f.seek(pos):光标回到指定位置
f.encoding:返回文件的字符编码
f.seekable():判断文件是否可以移动光标位置,类似tty文件是不可移动光标的
f.readable():判断文件是否可读
f.writable():判断文件是否可写
f.flush():强制将内存缓存中的内容写入硬盘
f.closed():判断文件是否是关闭状态
f.truncate([size]):从文件开头截断文件内容,size不输则会清空整个文件
5、遍历文件
for line in f: #此时f为一个迭代器
xxxx
遍历文件采用这种方法效率较高
6、修改原文件
修改文件有两种方式:
1)将文件全部读入内存,修改完成后再写入原文件,此方法不适用于大文件,因为可能导致内存爆满
2)将文件逐行遍历,将处理结果写入新文件,全部处理完以后使用新文件覆盖旧文件
7、with语句
为了避免程序中打开文件忘了关闭,可以使用with语句来自动关闭文件,当with下的语句执行完成后自动关闭文件:
with open("文件名","模式") as f:
xxxxxxxx
with open("file1") as f1,open("file2") as f2: # 同时打开多个文件,使用逗号分隔
xxxxxxxx
三、字符编码与转换
python中使用的字符编码是unicode,进行字符编码时要先将待转码的字符串解码为unicode,再由unicode编码为目标编码。
1)encode("目标编码"):编码,由unicode编码为其他编码
2)decode("待解编码"):解码,由其他编码解码为unicode
python3中字符串默认使用unicode来保存
#!/usr/bin/env python3 import sys source_code = "原字符串" # sys.getdefaultencoding()方法用于获取文件的编码 print("文件编码:",sys.getdefaultencoding()) # python默认使用unicode,不需要decode,直接encode转为GBK编码 utf8_to_gbk = source_code.encode("gbk") # 先decode由gbk解码为unicode,再encode编码为gb2312 gbk_to_gb2312 = utf8_to_gbk.decode("gbk").encode("gb2312") print("UTF-8转为GBK:",utf8_to_gbk) print("GBK转为GB2312",gbk_to_gb2312)
四、函数
1、函数定义:
def 函数名(参数):
"""文档描述,建议说明本函数的功能"""
函数体
return 返回值
2、return返回值:
return返回值可以返回任意类型数据,且可以返回多个值,返回的多个值被保存在一个元组中。
3、参数:
定义函数的时候可以指定给函数传入参数,在定义时使用的参数为形式参数,函数调用时传入的参数为实际参数。
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # 位置参数 def func1(x,y,z): print(x) print(y) print(z) print('\n') # 定义函数时指定默认参数,默认参数在定义时设定默认值,调用时可以不传默认参数 def func2(x,y=2): print(x) print(y) print('\n') # 定义参数组:用于接收不定个数的参数,接收的参数放在一个元组中 def func3(*args): print(args) print('\n') # 定义接收不定个数的关键字参数,接收的参数放在一个字典中 def func4(**kwargs): print(kwargs) print('\n') # 位置参数与位置参数组混合定义 def func5(name, *args): print(name) print(args) print('\n') # 位置参数与关键字参数组混合定义 def func6(name, **kwargs): print(name) print(kwargs) print('\n') # 位置参数、默认参数、位置参数组混合定义 def func7(name, age=18, *args): print(name) print(age) print(args) print('\n') # 位置参数、默认参数、关键字参数组混合定义 def func8(name, age=18, **kwargs): print(name) print(age) print(kwargs) print('\n') # 位置参数、默认参数、位置参数组、关键字参数组混合定义 def func9(name, age=18, *args, **kwargs): print(name) print(age) print(args) print(kwargs) print('\n') # 位置参数调用,调用时实参和形参一一对应 func1(1,2,4) # 关键字调用:调用时给形参赋值时指定形参名,与形参顺序无关 func1(x=1,y=2,z=4) func1(z=4,x=1,y=2) # 位置参数和关键字参数在调用时可以混用,但关键字参数不可以放在位置参数之前 func1(1,2,z=4) func1(1,z=4,y=2) func2(1,3) func2(2) func3(1, 2, 3, 4) func3(*[1, 2, 3, 4, 5]) func4(name='zhanghaoyan', age=23, job='IT') func4(**{"name": "zhanghaoyan", "age" : 80, "job" : "IT"}) func5("zhanghaoyan", 20, "IT") func6("zhanghaoyan", bob="IT", sex="Man") func7("zhanghaoyan", 20, "IT", "Man") func8("zhanghaoyan", job="IT", sex="Man", age=20) func9("zhanghaoyan", 20, "IT", sex="Man")
4、局部变量与全局变量:
1)在函数中定义的变量就是局部变量,在程序的一开始定义的变量就是全局变量。
2)在函数中使用global 全局变量名来声明全局变量。
3)如果全局变量与局部变量重名,则局部变量在其作用域内生效
4)不能在函数内部直接修改字符串、数值类型的全局变量,但是列表,字典,集合等其他数据类型可以在函数中直接改
#!/usr/bin/env python3 # -*- coding:utf-8 -*- school = "OldBoy" def change_name(name): global school school = "Mage Linux" print(name,school) print("school befor",school) change_name("school:") print("school after:",school)
5、递归函数
函数中可以调用别的函数,在函数中调用自身,则就是递归函数。
1)递归函数要有明确的结束条件
2)每次进入更深一层递归时,问题规模应该比上一层减少
3)递归函数效率不高
#!/usr/bin/env python3 # -*- coding:utf-8 -*- def digui(n): print(n) if n/2 >1: return digui(n/2) print("----->",n) digui(10)
运行结果:
10
5.0
2.5
1.25
-----> 1.25
6、函数式编程
函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。而函数式编程(请注意多了一个“式”字)——Functional Programming,虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算。
我们首先要搞明白计算机(Computer)和计算(Compute)的概念。
在计算机的层次上,CPU执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言是最贴近计算机的语言。而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件越远。对应到编程语言,就是越低级的语言,越贴近计算机,抽象程度低,执行效率高,比如C语言;越高级的语言,越贴近计算,抽象程度高,执行效率低,比如Lisp语言。
函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。
函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。主要思想是把运算过程尽量写成一系列嵌套的函数调用。举例来说,现在有这样一个数学表达式:
(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);
这就是函数式编程。
7、高阶函数
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
def add(x,y,f): return f(x) + f(y) res = add(3,-6,abs) print(res)