本专题的目标:
掌握Python基础语法全体系
掌握Python编程的基本方法
文章很长(包含了所有基本语法)
注:后面的专题会有Python 进阶和高级语法
###############首先:本专题知识结构:##############
第一部分内容结构:
基本数据类型:
数值类型及运算方法
字符串类型及操作方法
字节串类型及操作方法
分支与循环
分支结构及用法
循环结构及用法
实例1:自然对数的计算
random库的使用
蒙特卡洛方法求解自然对数
程序的异常处理:
异常处理的基本使用
异常处理的高级使用
函数定义与使用:
函数定义与使用详解
lambda函数
函数递归
第二部分内容结构:
组合数据类型:
集合:集合类型
序列:元组类型,列表类型
字典:字典类型
组合数据类型的使用:
集合,元组,列表,字典的使用
操作符,函数和方法
实例2:文本清洗及统计
字符文本的高效统计
中国大学信息清洗,去重及统计
文件的使用:
文件的打开和关闭
文件内容的读写
一二维数据格式化:
一二维数据的表示与处理
CSV格式与一二维数据存储
======================================================
第一部分内容:
基本数据类型:
Q:Python中有几种数据类型呢?
在Python 基础语法中总共包括9中数据类型,
数值类型:整数,浮点数,复数
字节类型:字符串,字节串
组合类型:列表,元组,字典,集合
数字类型:
它包括整数,浮点数,复数
1,整数类型:需要关注两点,一是无取值范围,二是有十,二,八,十六进制
2,浮点数类型:需要关注四点,一是有取值范围,二是不确定为数问题,三是科学计数法,四是大精确浮点运算
3,负数类型:与数学中基本一致,要会获取实部和虚部
整数类型:
它没有其他编程语言中所存在的长短整形之分,它的范围是没有的,只要是内存够大,
它有四种形式:
二进制:0b 或 0B
八进制:0o 或 0O
十六进制:0x或0X
十进制,
不同进制之间是可以直接进行比较的,
浮点数类型:
它的科学计数法表达:
使用字母e 或E 作为幂的符号,以10为基数,
格式:
它有取值范围和精度,可以通过sys.float_info 查看,(要引入sys库)
max 和min 是范围,epsilon 是精度,
不确定尾数:
它是计算机运算存在的问题,因为计算机里无法精确的存储小数,
如果在计算机内部进行运算浮点数就可能带来不确定尾数的问题,
可以通过round() 来解决,
round(0.1+0.2,1) 第二个参数是小数点后取几位
round(x,d) :对x四舍五入,d 是小数截取位数,
大精确浮点数运算:
我们知道整数是没有取值范围的,
所以我们可将浮点数的运算转换为整数运算:
例如1.2e-3 可以表示为12 和 4 0.01 转化为1 和 2
进一步将小数位数对齐,12,4 100,4
运算结果是: 112,4 即0.0112
(图)
复数:
z = a+bj
z.real
z.imag
数值运算:
数值之间怎么进行运算呢?
python 有三种方式:
操作符,函数和方法:
操作符:
它可以和等号在一起形成赋值增强操作符,
注: Python没有++ 操作,
整数的位运算:
位运算按照二进制方式逐位进行,
位运算只对整数有作用,
位运算符:
六种:
与或非 异或 左移 右移
& | ~ ^ << >>
字符串类型及操作方法
其实python中只提供了# 的注释,
但是,如果一个字符串没有赋值,那么它也可以 当做注释,
索引
切片: 不包含最后一个,
逆序方法:
【::-1】
字符串有个特殊的字符:转义符 \
转义符是表达特殊字符串或功能的方式,
转移符可以表达特定字符的本意
"这里有个双引号(\")"
转义符可以形成一种组合,表达一些不可打印的含义,
\b 回退(前一个光标的位置)
\n 光标回到下行首
\r 光标回到本行首
字符串的操作符:
x+y
n*x x*n
x in s
字符串操作函数(内置函数)
len(x)
str(x) 将任意类型转为字符串
hex(x) oct(x) 整数x的十六进制或八进制小写形式字符串
chr(x)
ord(x)
字符串处理方法:
方法:指的是封装到类中的函数,
str.lower() .upper()
str.split(sep =None) 默认空格分隔
str.count(sub) 子串出现的次数
str.replace(old,new)
注:这几类都是不改变字符串本身的,
str.center(width,[fillchar])
"python".center(20,"=")
str.strip(chars)
从str中去掉其左侧和右侧chars 中列出的字符,
str.join(iter)
在iter变量除最后一个元素外,每个元素后增加一个str
",".join("12345")
它可以将字符串分隔,
注: join 和split可以一起使用
字符串的格式化方法:
format() 方法:
槽 “{}”.format()
字节串类型及操作方法
字节串:由0个或多个字节组成的有序字节序列
与字符串类似:
单行字节串由一对单引号或一对双引号表示
多行字节串由三个单引号或三个双引号表示
但是要加个b
例如: b"helloworld"
与字符串的区别:
它是由字节组成,
字符串是由字符组成,
Python定义字节串的目的是为了严格控制对内存的使用,
所以,字节串就是计算机存储空间的表达
注:由于字节串是由字节组成的,所以
字节串只允许ascii 字符,
它也可以索引和切片,
也有操作符,
+
*
in
字节串的操作函数:
只有一个len()
字节串的处理方法:
bytes.lower() .upper()
bytes.split(sep=None)
bytes.count()
bytes.center()
bytes.strip()
bytes.replace()
总结:我们平时处理文本的时候是用字符串的,
那么什么时候使用字节串呢?
我们只有在处理和内存相关的内容时我们才会使用字节串,
分支与循环
分支结构及用法
单分支:
if <条件>:
<语句块>
二分支:
if <条件>:
<语句块>
else:
<语句块>
它还有它的紧凑形式:
<表达式> if <条件> else <表达式>
注 :紧凑形式的元素只能是表达式,不能用于语句
多分支:
if <条件>:
<语句块>
elif:
<语句块>
else:
<语句块>
条件判断及组合:
Python 语言提供True 和False表示真假
任何判断产生的结果都是True 或False
False 的等价值:
None
0
0.0
0j
''
()
[]
{}
set()
条件的组合:
and or not
与 或 非
循环:
遍历循环for和无限循环while
遍历循环及用法
for <循环变量> in <遍历结构>:
<语句块>
它每次循环,都是从遍历结构中逐一提取元素,放在循环变量中,并执行一次语句块。
遍历循环可以用于任何遍历结构
计数循环(N次)
计数循环(特定次)
for i in range(m,n,k)
字符串遍历循环
for c in s:
列表遍历循环
for item in ls:
文件遍历循环
for line in fd:
元组遍历循环
集合遍历循环
字典遍历循环
......
无限循环及用法
while <条件>:
<语句块>
循环的控制:
break 和continue 可以和for () 和 while() 一起使用。
循环的高级用法
循环完成的奖励:else扩展
就是如果循环没有碰到break ,那么它就会得到else 奖励,
实例1:自然对数的计算
e的定义如下:
求解它有两种方法:
一是公式法,
二是蒙特卡洛方法,
公式法,我们可以取一个很大的值,代入得到e的近似值,
但是要注意,浮点数计算的是有范围的,如果想更精确可以使用之前讲的内容,
我们主要看下面的:
random库的使用
蒙特卡洛方法求解自然对数
代码见:https://www.cnblogs.com/zach0812/p/11271928.html
程序的异常处理:
异常处理的基本使用
首先我们要理解异常:
所有非解释器返回的非正常功能的错误信息就是异常,
1,应对所有的异常:
try:
<语句块>
except:
<语句块>
2,应对特定的异常:
try:
<语句块>
except <异常类型>:
<语句块>
eg:
try:
1/0
except:
print("某种原因异常)
try:
1/0
except ZeroDivisionError:
print("除数不为零)
异常可以在函数等各类复杂的情况中使用:
例如:
def func(a):
try:
b *=100/a
except ZeroDivisionError:
print("除数出错了")
return -1
except :
print("未知错误")
return -2
异常处理的高级使用
我们知道基本用法是
try except
高级用法是
try except else finally
try:
<语句块>
except:
<语句块>
else:
<语句块>
finally:
<语句块>
其中,try except 含义不变,except可以有多个,
else的语句 是当try 中的语句块无异常的奖励
finally 是一定要执行的语句块。
就是如果try 中没有异常,1 3 4 会被执行,
如果发生了异常,1中异常前会被执行,2 4 会执行。
当try except else finally 遇到函数:
总结:
无论return 在哪里,finally一定要执行的
try 中有return ,else 不执行
finally 中的return 会覆盖之前的所有return
函数定义与使用:
这里会涉及到四个保留字:
def return global
lambda
函数的定义和调用:
函数是一段代码的抽象表示
函数的参数传递:
可以有参数,也可以没有,但是()一定要有
这里有四个方面:
位置传递和名称传递
def fact(n,m):
return s//m
>>>fact(10,5) #位置传递 按顺序
>>>fact(n = 10,m = 5) # 名称传递 按名称
可选参数传递
可选参数:函数为某些参数指定默认值,构成可选参数
注: 可选参数必须放在非可选参数的后面
def fact(n,m=1):
return s//m
>>>fact(10) #可选参数 m 可以不传
>>>fact(10,5) #可选参数 m 也可以传
可变参数传递:元组形式和字典形式
函数可以接收不确定总数的参数变量
元组形式:
def <函数名>(<参数>,*b):
<函数体>
return <返回值>
字典形式:
def <函数名>(<参数>,**d):
<函数体>
return <返回值>
例子:
def func(n,*b):
return n
>>> func(10,3) #b = (3,)
>>> func(10,3,5,8) #b = (3,5,8)
#所有可变参数作为一个元组变量。
def func(n,*d):
return n
>>> func(10,a = 3) #d = {a:3,}
>>> func(10,a=3,b = 5,c = 8) # d={a:3,b:5,c:8,}
#所有名称传递方式的可变参数作为一个字典变量。
真实代码:
def func(a,b,*args ,**kwargs):
print(args)
print(kwargs.keys())
func(1,2,3,5,4,c= 5)
代码输出如下:
(3, 5, 4)
dict_keys(['c'])
多返回值
return 保留字用来传递返回值 或表示函数结束
函数可以有返回值,也可以没有返回值,可以有return 也可以美原油
return 可以传递0个返回值,也可以传递任意多个返回值
def func(n ,m = 1):
s = 1
return s//m,n,m
>>> func(10,5)
(0, 10, 5)
>>>a,b,c = func(10,5)
>>>print(a,b,c)
0 10 5
1,如果返回多个值,返回的其实是个元组,
2,如果返回一个值,返回的是个int
3,如果返回0个值 ,返回的其实是个None 它的类型是NoneType
第三点如下证明:
def func(n ,m = 1):
s = 1
return
>>>a= func(10)
>>>type(a)
>>>type(None)
局部变量和全局变量:
局部变量和全局变量是各个编程语言中都有的概念,
规则1:局部变量和全局变量是不同的变量
局部变量是函数内部的占位符,与全局变量可能重名但不同
函数运算结束后 ,局部变量被释放
使用global保留字在函数内部声明并使用全局变量
规则2:局部变量为组合类型且未创建,等同于全局变量
ls =["F","f"]
def func():
ls.append("c")
return
>>>ls
['F','f','c']
深入的解释就是:
Python语言调用函数时,它用的是组合数据的引用,而不是自己创建一个,
ls =["F","f"]
def func():
ls=[] # 这时候的ls 就是真实的创建了,而不是全局变量了
ls.append("c")
return
>>>ls
['F','f']
使用规则总结:
基本数据类型,无论是否重名,局部变量与全局变量不同
可以通过global保留字在函数内部声明使用全局变量
组合数据类型,如果局部变量未真实创建,则使用的是全局变量。
lambda函数:
lambda函数返回函数名为结果,
我们知道,一般的函数都是返回运算结果,lambda函数返回的是函数的名字,
我们叫它匿名函数,因为它本身定义的是操作,它并没有名字,它返回的才是名字,
1,lambda函数是一种匿名函数,即没有名字的函数
2,使用lambda保留字定义,函数名是返回结果,
3,lambda函数用于定义简单的,能够在一行内表示的函数,
如果是复杂的函数,请使用def ,(而且可以通过装饰器扩展功能)
<函数名> = lambda <参数> : <表达式>
f = lambda x,y :x+y
>>>f(10,5)
15
f = lambda : "我是个lambda函数,我返回函数名字"
>>>print(f())
我是个lambda函数,我返回函数名字
函数递归:
函数定义中调用函数自身的方式:
它有两个要素:
链条:计算过程存在递归链条
基例:存在一个或多个不需要再次递归的基例。
递归的实现:
框架:
函数+分支结构
1,递归本身是个函数,需要函数定义方式描述
2,函数内部,采用分支语句对输入参数进行判断
3,基例和链条,分别编写对应的代码,
对于基例我们直接给出它的值,
对于非基例的部分,我们要给出链条的描述
例子:
逆序字符串:
def rvs(s):
if s=="":
return s
else
return rvs(s[1:]) +s[0]
斐波那契数列:
def func(n):
if n ==1 or n == 2:
return 1
else:
return func(n-1) +func(n-2)
第二部分内容:
组合数据类型:
组合数据类型概述:
组合数据类型:包含一组数据且作为单一管理结构的数据类型
顺序性:一组数据以无序或有序方式组织
一致性:一组数据以相同或不同的类型组织
索引性:一组数据能否以及采用序号或自定义索引方式组织
Python组合数据类型: 3大类 7小类
集合(无序,非一致,无索引):可变集合(set),不可变集合(frozenset)
序列(有序,非一致/一致,序号索引):元组,列表,字符串,字节串
字典(无序,非一致,自定义索引):字典
可变类型和不可变类型:
有些类型创建后其值不能被改变,有些却可以随时被改变:
1,可变类型:值可以改变的类型,例如:列表,字典等
2,不可变类型:值不可以被改变的类型,例如:数值类型,字符/字节串,元组等
另外有个可哈希性和hash() 函数:
哈希是对其的一种摘要返回是个确定值,这个哈希值与这个数据之间会形成对应关系
所以,如果类型是可变的,那么就不可以计算哈希值,
1,hash(x) 函数返回x的一个哈希值
2,并不是所有的类型都可以被哈希,不可变类型可以被哈希
3,例如,数值类型,字符/字节串,元组 都是可以被哈希的,
列表,字典不能被计算哈希值。
总结:
关于可变不可变
它指的是(除了赋值以外)是否能改变变量的值,
能改变的叫可变,不能改变的叫不可变类型
可变的不能被哈希,不可变的能被哈希
集合:集合类型
一组数据的集合
无序,非一致,无索引
并且集合中必须都是不可变类型,如果是可变类型,本来它和别的元素不一样,它变了就和别的相同了,
无序:元素间没有顺序
非一致:元素的类型可以不同
无索引:不能对某个元素进行定点索引,但是可以遍历或随机获取元素
集合也分两种:
可变集合类型和不可变集合类型:
可变集合类型set() :集合元素的个数可以不断增加或减少
它的元素是不可变的,但是它的个数是可变的。
不可变集合类型frozenset():集合创建后不可改变
它的个数也不可变。它的使用很少。。。
集合类型的创建:
对于可变集合创建:
使用{} 或者set()函数
>>> A = {"p","y",123}
>>> B = set("pypy123")
>>> B
{'y', '3', '1', 'p', '2'}
>>> A-B
{123}
>>> B-A
{'3','1','2'}
对于不可变集合类型:
使用frozenset() 来创建:
>>> A =frozenset("pypy123")
>>>A
frozenset({'y', '3', '1', 'p', '2'})
表示为frozenset({ }) 形式
序列:元组类型,列表类型,字符/字节串
有序:元素间存在顺序,因此,可以存在值相同的多个元素
非一致:元组和列表中的元素的类型可以不同
一致:字符串和字节串中元素的类型必须相同
序号索引:采用正向递增或反向递减的方式索引,根据序号精确访问单个元素
元组类型:创建后一般不能被修改的序列类型
创建:
使用tuple() 函数或者 用逗号,
>>>a = tuple("pypy123")
>>> a
('p', 'y', 'p', 'y', '1', '2', '3')
>>>b = 123,456
>>>c = (123,456,)
列表类型:创建后可以随时被修改
创建:
使用list () 函数,或者使用[ ]
注意:这时就不能省略方括号,如果省略就成元组类型了,
>>> a = list("python")
>>> a
['p', 'y', 't', 'h', 'o', 'n']
序列的索引:
正向递增和反向递减的方式:
索引和切片和字符串类似,(本质上,字符串也是序列类型)
字典类型:
字典类型是一组包含映射关系的数据组合,
无序:元素间不存在顺序,因此字典所包含的键值对元素不能相同
非一致:每个元素都是一个键值对,其键和值的类型均可不同
自定义索引:键值对相当于对“值”建立了新的以“键”方式的索引
这里要说 映射:
它是一种键和值的对应
键是索引
值是数据
创建字典: 使用dict() 函数 或 { }里放键值对
注:空{} 是个字典,不是集合,空集合是set()
>>> d = {"中国":"北京","美国":"华盛顿"}
>>> d
{'中国': '北京', '美国': '华盛顿'}
索引的时候要用key索引
>>>d['中国']
北京
组合数据类型的使用:
集合,元组,列表,字典的使用方法:
这里的使用方法都包括三个方面:
1,操作符,
2,函数
3,方法
集合类型的使用:
操作符:包含(in) ,交(&),并(|),差(-),补(^),比较(> = <)
函数:len() ,set()
方法:
.add() ,.remove(),.discard(),.clear(),.pop(),.copy()
.intersection(),.union(),.difference(),symmetric_difference()
.intersection_update(),.update(),.difference_update(),.symmetric_difference_update(),
.isdisjoint(),.issubset(),.issuperset(),
操作符:
in 元素判断, x in S
not in x not in S
& 集合的交集,返回一个新集合 S&T
| 集合的并集,返回一个新集合 S|T
- 集合的差集,返回一个新集合 S-T
^ 集合的补集,返回一个新集合 S^T
比较操作符:
> = <
< 真子集判断
<= 自己判断
> 真超集判断
>= 超集判断
== 全相同判断
!= 不相同判断
内置操作函数:
len(x) 返回集合元素的个数 len(S)
set(x) 转换组合类型,创建一个集合 set([1,2,3]) {1,2,3}
注:将其他组合类型转换为集合时,如果有元素重复了,它会自动去重
集合的方法:
集合元素的维护类方法:
.add(x) 增加x 到集合 S.add(x)
.remove() 删除S中的元素x ,如果x不存在,产生KeyError S.remove(x)
.discard() 删除S中的元素x,如果x不存在,不报错 S.discard(x)
.clear() 删除S 中的所有元素 S.clear()
.pop() 随机返回S中的一个元素,如果S为空,产生KeyError S.pop()
.copy() 复制集合S ,产生一个副本
集合的运算类方法:
这里和操作 & | - ^ 是一样的
.intersection(x) 集合的交集,返回一个新集合 S.intersection(T) 不更新S
.union(x) 集合的并集,返回一个新集合 S.union(T) 不更新S
.difference(x) 集合的差集,返回一个新集合 S.difference(T) 不更新S
.symmetric_difference(x) 集合的补集,返回一个新集合 S.symmetric_difference(T) 不更新S
如果想让它更新原有集合:
这里只有并集和原有的有区别,其他的都是在后面直接加update
.intersection_update(x) 集合的交集,返回一个新集合 S.intersection_update(T) 更新S
.update(x) 集合的并集,返回一个新集合 S.update(T) 更新S
.difference_update(x) 集合的差集,返回一个新集合 S.difference_update(T) 更新S
.symmetric_difference_update(x) 集合的补集,返回一个新集合 S.symmetric_difference_update(T) 更新S
集合的比较类方法:
.isdisjoint(x) 无关判断,两个集合之间无共同元素则返回True S.isdisjoint(T)
.issubset(x) 子集判断,如果x是集合的子集则返回True S.issubset(T)
.issuperset(x) 超集判断,如果x是集合的超集则返回True S.issuperset(T)
集合的应用场景:
主要有两种:
包含关系比较:
>>>1 in {1,2,3}
>>>['p','y'] >= ['p','y',123]
数据去重:(最典型)
>>>ls = ['p','p'.'y','y',123]
>>>s =set(ls) #利用集合无重复元素的特点
>>>s
{'p','y',123}
>>>l =list(s) #还可以将集合再转换为列表
>>>l
['p','y',123]
元组类型的使用:
也是有操作符,函数,方法:
操作符:in ,+,*,比较(> = <)
函数:len() ,tuple() ,min() ,max()
方法:.index() ,.count()
操作符:
in 元素判断 1 in (1,2,3)
not in 元素判断 1 not in (1,2,3)
+ 连接多个元组,返回一个新元组 (1,2,3) +(4,5,6)+(7,8)
* 重复元组多次,返回一个新元组 (1,2,3)*3或3*(1,2,3)
比较操作符:但是元组的比较操作符是建立在逐个元素上的,不是像集合建立在整体上。
规则:
按照顺序,逐个元素比较,只要有元素比较得出True/False,就返回结果
比较时元素之间要有可比性
eg :
< (11,2) <(13,1) True
<= (11,2) <= (11,1,2) False
> (11,2) >(10,"abc") True
>= (11,2) >=(11,2) True
== (11,2) ==(11,2,1) False
!= (11,2) != (1,2) True
内置操作函数:
len(x) 返回元组元素的个数 len(S)
tuple(x) 转换其他组合类型为元组,创建一个元组 typle([1,1,2,2,3]) (1,1,2,2,3)
min(x) 返回元组中最小的元素 min((1,1,1,2,2,3))
max(x) 返回元组中最大的元素 max((1,1,1,2,2,3))
注: min 和max 要求各个元组之间可比
元组的方法:
.index(x) 返回元组中第一次出现x的位置 tp.index(x)
.count(x) 返回元组中x出现的总次数 tp.count(x)
元组类型无增删改查需求,只能索引,切片,查询和统计
列表类型的使用:
同样的列表也是有操作符,函数和方法:
操作符:in ,del ,+ ,* ,比较(> = <)
函数:len(),list() ,min(),max()
方法: .append(),.insert(),.extend() ,.remove(),.clear()
.copy() ,.pop() ,.reverse(),.index(),.count(),.sort()
基本操作符:(因为列表中的元素是可以删除的,所以相对元组多了个del)
in 元素判断 1 in [1,2,3]
not in 元素判断 1 not in [1,2,3]
del 删除列表中元素或列表片段 del ls[2] 或del ls[:-2]
+ 连接多个列表,返回一个新的列表 [1,2,3]+[4,5,6]
* 重复列表多次,返回一个新的列表 [1,2,3]*3 或3*[1,2,3]
比较操作符:
也是按照顺序,逐个元素比较,只要元素比较得出True/False,就返回结果
比较时,元素间要有可比性
eg:
< [11,2] <[13,1] True
<= [11,2] <=[11,1,2] False
> [11,2] >[10,"abc"] True
>= [11,2] >=[11,2] True
== [11,2] ==[11,2,1] False
!= [11,2] !=[1,2] True
内置的操作函数:
len(x) 返回列表的元素的个数 len(ls)
list(x) 将其他组合类型转换为列表,创建新列表 list((1,2,1,1,2,2,3))
min(x) 返回列表中最小的元素
max(x) 返回列表中最大的元素
列表的方法:
增删方法:
.append(x) 在列表的最后增加一个元素x ls.append(x)
.insert(i,x)在列表的第i位置增加元素x ls.insert(i,x)
.extend(lt) 在列表的最后增加一个新列表 ls.extend(lt)
.remove(x) 删除列表中第一次出现的x ls.remove(x)
.clear() 删除列表中所有的元素 ls.clear()
维护查询:
.copy() 拷贝列表中所有元素,生成一个新列表 lt = ls.copy()
.pop(i) 将列表中第i位置的元素取出并删除该元素 ls.pop(i)
.reverse() 列表中顺序元素逆序 ls.reverse()
.index(x) 返回列表中第一次出现x的位置 ls.index(x)
.count(x) 返回列表中x出现的总次数 ls.count(x)
.sort() 对列表进行排序,默认是递增 ls.sort()
关于排序还有内置函数sorted(),后面会说到它,
列表的小练习:
定义空列表ls ls = []
向ls 中新增5个元素 ls +=[1,2,3,4,5]或ls.extend([1,2,3,4,5])
修改ls 中第2个元素 ls[1]=6
向ls中第2个位置增加一个元素 ls.insert(1,7)
从ls中第1位置删除一个元素 del ls[0]
删除ls中第1-3位置的元素 del ls[1,4]
判断ls 中是否有数字0 0 in ls
向ls 中新增数字0 ls.append(0)
返回数字0所在的索引 ls.index(0)
ls的长度 len(ls)
ls中最大元素 max(ls)
清空ls ls.clear()
列表类型的使用场景:
列表使用于组织数据:
列表用来组织数据,非常灵活,它是最常用的组合数据类型
列表可用于表示一组有序数据或一组顺序无关的数据,进而操作它们,
列表将用于表达一二维数据
列表计算性能并不高,对于大规模数据,建议采用第三方库,NumPy中的ndarray 数组
字典类型的使用:
同样的字典也是有操作符,函数和方法:
操作符:in ,del, == ,!=
函数: len(),dict() ,iter()
方法:.items(),.keys() ,.values() ,.pop() ,.popitem()
.update(),.clear(),.copy(),.get()
基本操作符:
in 元素判断 'a' in {'a':1,'b':2}
not in 元素判断 'a' in {'a':1,'b':2}
del 根据键来删除字典中的单个元素 del d['a']
比较操作符:
注:字典不支持 > < 的比较
== 判断两个字典是否相同 d == {'a':1,'b':2}
!= 判断两个字典是否不同 d != {'a':1,'b':2}
内置操作函数:
len(d) 返回字典的元素个数 len(d)
dict() 创建一个字典,一般用于创建空字典 dict()
iter() 根据字典d的键形参一个迭代类型 iter(d)
例如:
>>>d={'a': 'hello world', 'b': 'i love you '}
>>>a = iter(d)
>>> for key in a:
print(d[key])
hello world
i love you
字典类型的方法:
字典的元素获取(键值对)
.items() 返回字典所有键值对,键值对采用(key,values)元组形式返回 d.items()
.keys() 返回字典的键 d.keys()
.values()返回字典的值 d.values()
.pop(k) 取出特定键k对应的值,并删除键值对 d.pop('a')
.popitem() 随机从字典中取出一个键值对,以(key,value)元组形式返回 d.popitem()
字典的维护方法:
.update(t) 扩展其他字典t的内容到当前字典中,键重复的会替换,会覆盖 d.update(t)
.clear() 删除字典中的所有元素 , d.clear()
.copy() 拷贝字典中所有元素,生成一个新字典 t = d.copy()
.get(k,default) 键k 存在则返回对应值,否则返回default d.get('a',0)
实例2:文本清洗及统计
文本类信息清洗及统计的可能需求场景:
从多个来源获得的格式不一的文本型数据
进行汇总及初步统计
难点:多个来源数据的清洗,格式化及归一化,形同内容的去重等
程序需求:
中国参与MOOC 建设的大学有多少所?
三个平台:
中国大学mooc https://www.icourse163.org/university/view/all.htm
学堂在线 http://www.xuetangx.com/partners
好大学在线 https://www.cnmooc.org/school/view/list.mooc
思路:从上述三个来源获取大学名称,清洗并去重,统计后得到结果
步骤:
首先思考获取数据要不要用爬虫去做?
(适合爬虫的不要用手工去做,适合手工的也不要用爬虫去做)
适合手工完成:一次性的,数量较少的,数据不复杂
适合爬虫完成:周期性采集,爬取站点较多,数据结构复杂但有规律
这里采用手工的方法,
对于中国大学mooc:
将对应的HTML代码保存为文本形式,保存在icourses.txt文件中
编写icourses.py ,提取其中大学的信息,输出空格分隔的大学名称
#icourses.py
fi = open("d:/icourses.txt","r")
ls = []
for line in fi:
if "alt" in line:
ls_temp = line.split('"')
uName =ls_temp[-2]
if "大学生" in uName: #去掉“全国大学生数学建模竞赛组织委员会”类似的机构
continue
if "大学" in uName or "学院" in uName:
ls.append(uName)
str_ls = " ".join(ls)
print(str_ls) #join会形成个字符串
print(len(ls))
fi.close()
结果是:287所
对于学堂在线:
我们换种方法:
直接在浏览器页面拷贝内容,保存在xuetangx.txt文件中
编写代码xuetangx.py ,提取其中的大学信息,输出空格分隔的大学名称
此时,文件中的信息就十分混乱了,含有很多重复的信息
fi = open("d:/xuetangx.txt","r")
U = set() #空集合 #就算是有重复的加也加不进
for line in fi :
if "慕课" in line:
continue
if "大学" in line or "学院" in line:
U.add(line.strip("\n"))
print(" ".join(U)) #得到空格分隔的字符串
print(len(U))
fi.close()
结果是: 167
这里要注意,因为文件的数据不是很规则(直接拷贝不如HTML代码规范),
所以我们就不能再使用列表了,应该利用集合的去重特点,
对于好大学在线:
直接在浏览器页面拷贝内容,保存在cnmooc.txt文件中
编写代码cnmooc.py ,提取其中的大学信息,输出空格分隔的大学名称
fi = open("d:/cnmooc.txt","r",encoding="utf-8")
U = set() #空集合 #就算是有重复的加也加不进
for line in fi :
if "大学" in line or "学院" in line:
U.add(line.strip("\n"))
print(" ".join(U)) #得到空格分隔的字符串
print(len(U))
fi.close()
结果:101
解决问题:汇总各程序运行结果,进行最终结果统计
汇总结果
人工和自动?
如果程序只考虑运行少数几次,可以不必追求完美,直接人工做就好了,
如果我们将程序变得很复杂,仅仅是为了全自动,这就有点得不偿失了,
我们人工的将前三个程序的结果拷贝到程序中作为输入:
ic = "北京大学 ..."
xt = "中国创业学院 北京体育学院 ..."
cm = "新竹清华大学 ..."
U = set()
U |= set(ic.split()) #将ic转换后的列表变为集合并和U或下
U |= set(xt.split()) #将ic转换后的列表变为集合并和U或下
U |= set(cm.split()) #将ic转换后的列表变为集合并和U或下
ls = list(U) #将U 集合转化为列表(这是为了能给它排序)
ls.sort() #排序
print(" ".join(ls))
print(len(ls))
如果对结果有疑问,可以人工审核,去掉即可。
通过这个例子主要是理解对文本数据类型进行出来的时候的各种操作,
去重统计
文件的使用:
文件的使用方法:
文件是数据的抽象和集合
文件形式和二进制形式是文件的两种不同展示方式
文本方式采用统一的编码解释文件,二进制方式采用字节解释文件
Python语言的文件使用理念和其他语言一致,如c语言
文件处理的步骤:打开-操作-关闭
a = open(,)
##############
a.read(size)
a.readline(size)
a.readlines(hint)
##############
a.write(s)
a.writelines(lines)
a.seek(offset)
a.close()
文件的打开:
<文件句柄> = open(<文件名>,"打开模式",<编码方式>)
其中的打开模式:
r 只读
w 覆盖写
x 创建写
a 追加写
b 二进制文件模式
t 文本文件模式,默认就是它
+ 与r/w/x/a 一起使用,在原有基础上增加同时读写功能
最后一个是编码方式:
encoding = " "
默认是跟平台有关 The default encoding is platform dependent
例子:
文本形式:
fp = open("f.txt","r",encoding="utf8")
print(fp.readline())
fp.close()
二进制方式:
fp = open("f.txt","rb",encoding="utf8")
print(fp.readline())
fp.close()
文件内容的读取:
有三种操作方法:
f.read(size =-1) :读入全部的内容,如果给出参数,读入前size
f.readline(size=-1) :读入一行的内容,如果给出参数,读入该行前size
f.readlines(hint=-1) :读入所有行的内容,以每行为元素形成列表,
如果给出参数,读入前hint 行
注:read 和readline在文本打开时读的是字符的数量,
在二进制打开读的是字节的数量
readlines 读的是行
文件的全文操作:
方式1:一次读入,统一处理(推荐)
fi = open(fname,"r")
txt = fi.read()
#对txt处理
fi.close()
注:文件大小有上限,但是处理几兆还是可以的,由于一次读入内存,处理起来比较快
方式2:按数据读入,逐步处理
fi = open(fname,"r")
txt = fi.read(20)
while txt != "":
#对txt处理
txt = fi.read(20)
fi.close()
注:它适合处理大数据文件,
文件的逐行操作:
方法1:一次读入,分行处理
fi = open(fname,"r")
for line in fi.readlines(): #readlines()返回的是列表
#对line 进行处理
fi.close()
方法2:分行读入,逐行处理(推荐)
fi = open(fname,"r")
for line in fi:
#对line处理
fi.close()
注:它适合非常大的文件,
数据的文件写入:
操作方法:
前两个是用来写入的,第三个是用来辅助写入的
f.write(s) 向文件写入一个字符串或字节流
f.writelines(lines) 将一个元素全为字符串的列表写入文件
f.writelines(["中国","法国","美国"]) 写入结果是:中国法国美国
f.seek(offset) 改变当前文件的操作指针的位置,
offset 含义如下:
0 开头
1 当前位置
2 文件结尾
例子:
fp = open("output.txt","w+")
ls = ["中国","法国","美国"]
fp.writelines(ls)
fp.seek(0)
for line in fp:
print(line)
fp.close()
一二维数据格式化:
数据组织的维度
维度:是一组数据的组织形式
一组数据可以被组织成一个线性的序列,也可以被组织为一个二维的数据
所以从一组数据到一组有组织的数据是需要维度的概念的,
数据维度包含以下:
1,一维数据:由对等关系的有序或无序数据构成,采用线性方式组织
2,二维数据:由多个一维数据构成,是一维数据的组合形式,(最常用)
3,多维数据:由一维或二维数据在新的维度上扩展形成
4,高维数据:利用“键值对”展示数据间关系的数据组织方式,(最常用)
html 和 json 都是高维数据的体现
如何表达数据的维度呢?
一维数据:对应列表(有序) 和集合(无序)等类型
二维数据:对应列表(二维列表)类型
多维数据:对应列表(多维列表)类型 (很少见)
高维数据:对应字典类型
一维数据的表示和处理
两种表达方式:
如果数据间有序,使用列表类型
ls= [1,2,3,4,5,2]
如果数据间无序,使用集合类型
set={1,2,3,4,5}
一维数据的存储方法有很多种:
大体分三类:
空格分隔:
中国 美国 日本
逗号分隔:
中国,美国,日本
其他特殊符号分隔:
中国$美国$日本
哪种好呢?
从标准化角度,逗号分隔的CSV方式好,
一维数据的读入处理:
从空格分隔的文件中读入数据
####中国 美国 日本#####
txt =open(fname).read()
ls = txt.split()
f.close()
从特殊符号分隔的文件中读入数据
####中国$美国$日本#####
txt =open(fname).read()
ls = txt.split('$')
f.close()
注:这时$ 符就不能用了
如果实在有个地方要用到$ ,那么可以在其前加\(转义符)
从逗号分隔的文件中读入数据
####中国,美国,日本#####
txt =open(fname).read()
ls = txt.split(',')
f.close()
注:这时,就不能用了 ,如果要用可以加转义符,
一维数据的写入处理:
从空格分隔的文件中写入数据
####中国 美国 日本#####
ls = ['中国','美国','日本']
f= open(fname,'w')
strTar = " ".join(ls)
f.write(strTar)
f.close()
从特殊符号分隔的文件中读入数据
ls = ['中国','美国','日本']
f= open(fname,'w')
strTar = "$".join(ls)
f.write(strTar)
f.close()
从逗号分隔的文件中读入数据
ls = ['中国','美国','日本']
f= open(fname,'w')
strTar = ",".join(ls)
f.write(strTar)
f.close()
字符串-----> 列表 用split()
列表 -----> 字符串 用join()
二维数据的表示与处理
二维数据的表示:
二维数据本质上是表格数据
二维列表表达数据的层次关系
二维数据的存储:
1,元数据(自定义数据)
2,Excel格式
3,数据库格式
4,CSV格式
哪种好呢?
从应用广泛性角度,CSV格式好
二维数据的读入处理:
从CSV格式的文件中读入数据:
f =open(fname)
ls = []
for line in f:
line = line.replace("\n","")
ls.append(line)
f.close()
注:每行形参的列表被当做一个元素
二维数据的写入处理:
将数据写入,保存文件是CSV 格式
ls = [[],[],,[]] #二维列表
f= open(fname,'w')
for item in ls:
str_Tar = ','.join(item)
f.write(str_Tar+'\n')
f.close()
注:每个列表元素本身以字符串写入
二维数据的逐一处理:
采用二层循环:
ls =[[],[],[]]
for row in ls:
for column in row:
print(ls[row][column])
CSV格式与一二维数据存储
CSV :Comma-Separated Values
国际通用的一二维数据存储格式,一般以.csv 为扩展名
每行一个一维数据,采用逗号分隔,无空行
Excel 及所有的数据库软件都可读入并导出它,一般编辑软件可编辑
CSV格式的特殊说明:
如果某个元素缺失,逗号仍要保留
二维数据的表头可以作为数据存储,也可以另行存储
逗号为英文半角逗号,逗号与数据之间无额外空格
二维数据的格式化:
针对二维数据,我们是按行存储呢?还是按列存储呢?
按行按列都可,具体由程序决定
一般索引习惯,ls[row][column] ,先行后列
如果是一般习惯,外层列表每个元素是一行,按行存
小结:
二维数据的表示:列表类型(二维列表),其中每个元素也是一个列表
CSV格式:逗号分隔表示一维,按行分隔表示二维
二维数据的处理:for循环 + .split() 和.join()