文章目录
一、Python概述
1.编程规范
(1)运用缩进体现代码的逻辑从属关系
(2)运用括号体现运算的隶属关系和顺序
(3)导入模块的顺序为:标准库、拓展库、自定义库,导入时最好只导入要使用的对象
(4)在每个类、函数定义、一段完整功能的代码后加空行,在运算符两端及逗号后面加空格
(5)语句不宜过长,长语句可使用续行符"\“或圆括号”()"表示一条语句
x = 1 + 2 + 3\
+ 4 + 5\
+ 6
y = (1 + 2 + 3
+ 4 + 5
+ 6)
(5)在关键语句后添加适当的注释
#单行注释
"""
多行注释
"""
'''
多行注释
'''
2.拓展库的导入和使用
导入 | 使用 | |
---|---|---|
1 | import 模块名 [as 别名] | 模块名/[别名].对象名 |
2 | from 模块名 import 对象名 [as 别名] | 对象名 |
3 | from 模块名 import * | 对象名 |
import math
print(math.sin(3)) #输出0.1411200080598672
import math as m
print(m.sin(3)) #输出0.1411200080598672
from math import sin
print(sin(3)) #输出0.1411200080598672
from math import sin as f
print(f(3)) #输出0.1411200080598672
from math import *
print(sin(3)) #输出0.1411200080598672
3.程序的__name__属性
__name__属性可以识别程序的使用方法:
①程序作为模块导入,其__name__属性被自动设置成模块名
②程序作为程序直接运行,其__name__属性被自动设置成字符串"__main__"
#建一个python文件hello.py输入:
def main():
if __name__ == '__main__':
print('This programme is run directly.')
elif __name__ == 'hello':
print('This programme is run as a module.')
main()
#运行hello.py,输出This programme is run directly.
#建一个python文件test.py输入:
import hello
#运行test.py,输出This programme is run as a module.
4.基本输入输出
名称 | 说明 | 使用 | |
---|---|---|---|
输入函数 | input() | 无论用户输入什么,input()均返回字符串 | input(‘Please input:’) |
输出函数 | print() | 输出的内容可以有多个,默认多个内容之间用空格隔开,所有内容输出后再输出一个换行符 | print(value 1, value 2, …, sep = ’ ', end = ‘\n’) |
x = input('Please input:') #输入[1, 2, 3]
print(x) #输出[1, 2, 3]
print(type(x)) #输出<class 'str'>
x = eval(x) #自动类型转换
print(x) #输出[1, 2, 3]
print(type(x)) #输出<class 'list'>
print(1, 2, 3)
print(4)
"""
输出:
1 2 3
4
"""
print(1, 2, 3, sep = ',', end = '\t')
print(4)
"""
输出:
1,2,3 4
"""
二、内置对象、运算符、表达式、关键字
1.常用的内置对象
(python中一切皆对象)
内置对象可直接使用,非内置对象需要导入模块才能使用
对象类型 | 类型名称 |
---|---|
数字 | int, float, complex |
字符串 | str |
字节串 | bytes |
列表 | list |
元组 | tuple |
字典 | dict |
集合 | set |
布尔型 | bool |
空类型 | NoneType |
异常 | Exception ValueError TypeError |
文件 | |
其他可迭代对象 | |
编程单元(函数,类,模块) |
2.常量和变量
(1)变量的理解
(变量不用事先声明)
①赋值过程
先计算等号右侧表达式的值,然后在内存中找一个位置存这个值,最后创建变量指向这个内存地址
②变量类型
python为强类型编程语言,即变量的类型根据运算或赋值自动推断
python为动态类型语言:即变量的类型可以随时改变
a = 1 #a为整型
b = 2.0 #b为浮点型
b = "python" #b现在为字符串型(字符串型可用""或''声明)
指定变量的数据类型可用强制转换实现
x = int(3) #x为3
y = float(3) #y为3.0
z = str(3) #z为'3'
查看变量类型可用type()函数实现
print(type(x)) #输出x的类型
(2)变量的命名
命名规则:
①变量名可由由字母、数字、下划线构成
②变量名不能以数字开头
③变量名区分大小写
常用法则:
①骆驼法则:除第一个单词外其余单词都以大写字母开头
②帕斯卡法则:每个单词都以大写字母开头
③蛇形法则:每个单词都用下划线隔开
(3)变量值的分配
①一个变量一个值:
a = 1
b = 2
c = 3
②多个变量多个值:
a, b, c = 1, 2, 3 #等价于a = 1, b = 2, c = 3
③多个变量一个值:
a = b = c = 1
3.数字
类型名 | 说明 | 举例 | |
---|---|---|---|
整数 | int | 有正负,不带小数 | 1 |
浮点数 | float | 有正负,带小数 | 2.0 |
复数 | complex | j表示虚部 | 1 + 2j |
(1)python支持任意大的数字
(2)两个实数相等的依据是两者之间的绝对值是否足够小,尽量避免直接比较两个实数的大小
print(0.4 + 0.1) #实数相加无偏差
print(0.4 - 0.1) #实数相减有偏差
print(0.4 - 0.1 == 0.3) #输出为False
print(abs((0.4 - 0.1) - 0.3) < 1e-6) #输出为True
(3)数字运算过程会自动进行类型转换
x = 1
y = 2.0
z = 1 + 2j
print(x + x) #输出2
print(x + y) #输出3.0,自动转为浮点型
print(x + z) #输出(2+2j),自动转为复数型
(4)复数的运算
x = 1 + 2j
y = 3 + 4j
print(x + y) #(4+6j)
print(x - y) #(-2-2j)
print(x * y) #(-5+10j)
print(x / y) #(0.44+0.08j)
print(abs(x)) #复数的模2.23606797749979
print(x.real) #复数的实部1.0
print(x.imag) #复数的虚部2.0
print(x.conjugate()) #共轭复数(1-2j)
(5)数字可用单个下划线分隔
但下划线不能在开头、结尾,也不能连续
print(1_000_000) #1000000
4.运算符和表达式
(1)表达式
使用除赋值运算符以外的其他任意运算符和函数调用连接的式子,单个常量或变量也是表达式
(2)运算符
①运算优先级:
算术运算符>位运算符>成员测试运算符>关系运算符>逻辑运算符>赋值运算符
②可以使用括号说明运算逻辑
运算符 | 说明 | |
---|---|---|
算术运算符 | + - * / // % ** | 加,列表、元组、字符串连接,正号 减,负号 乘,列表、元组重复 除 整除(向下取整) 取余,字符串格式化 幂运算 |
位运算符 | & | ~ ^ << >> | 位与 位或 位求反 位异或 左移位 右移位 |
成员测试符 | in is | 测试是否在其中 测试是否为同一对象 |
关系运算符 | <, <=, >, >= ==, != | 值的大小比较,集合的包含关系比较 |
逻辑运算符 | or and not | 逻辑或 逻辑与 逻辑非 |
赋值运算符 | ==及复合赋值运算符 | |
集合运算符 | & | ^ - | 集合交集 集合并集 集合对称差集 集合差集 |
算术运算符:
print(1 + 2) #3
print([1, 2, 3] + [4]) #[1, 2, 3, 4]
print((1, 2, 3) + (4,)) #(1, 2, 3, 4)
print('1, 2, 3, ' + '4') #1, 2, 3, 4
print(+1) #1
print(1 - 2) #-1
print(-1) #-1
print(3 * 4) #12
print([1, 2, 3] * 2) #[1, 2, 3, 1, 2, 3]
print((1, 2, 3) * 2) #(1, 2, 3, 1, 2, 3)
print(3 / 4) #0.75
print(3 // 4) #0
print(3 % 4) #3
print(3 ** 4) #81
print('%c, %d' % (65, 65)) #A, 65 格式化
位运算符:
x = 3 #011
y = 4 #100
print(x | y) #7 = 111
print(x & y) #0 = 000
print(~ x) #-4
print(x ^ y) #7 = 111
print(x << 1) #6 = 110
print(x >> 1) #1 = 001
成员测试符:
print('a' in 'abc') #True
print(type('a') is str) #True
关系运算符:
print(3 < 4 < 5) #True
print(3 < 4 > 2) #True
print('hello' < 'world') #True
print([1, 2, 3] < [1, 2, 4]) #True,列表值大小比较
print((1, 2, 3) < (1, 2, 4)) #True,元组值大小比较
print({1, 2, 3} < {1, 2, 4}) #False,集合是否为子集
print({1, 2, 3} == {1, 2, 4}) #False,集合是否相等
逻辑运算符
print(1 > 2 and a) #False,前面错不看后面,a不定义也不报错
print(1 < 2 or a) #True,前面对不看后面,a不定义也不报错
print(3 not in [1, 2, 3]) #False
print(3 and 5) #5
print(5 and 3) #3
print(0 and 5) #0(0当成false)
print(5 and 0) #0
集合运算符:
A = {1, 2, 3}
B = {1, 2, 4}
print(A | B) #{1, 2, 3, 4}
print(A & B) #{1, 2}
print(A ^ B) #{3, 4}
print(A - B) #{3}
print(B - A) #{4}
注意:python中不支持++和–
5.类型转换和判断
内置函数 | 说明 |
---|---|
int() | 其他类型转十进制整型 |
bin() | 十进制整型转二进制整型 |
oct() | 十进制整型转八进制整型 |
hex() | 十进制整型转十六进制整型 |
float() | 其他类型转浮点型 |
complex() | 其他类型转复数型 |
str() | 其他类型转字符型 |
ord() | 返回单个字符的Unicode码 |
chr() | 返回Unicode码对应的字符 |
list() | 其他类型转列表 |
tuple() | 其他类型转元组 |
dict() | 其他类型转字典 |
set() | 其他类型转集合 |
type() | 查看类型 |
isinstance() | 判断类型 |
eval() | 字符串求值,类型转换 |
x = int('18')
print(x) #18
print(type(x)) #<class 'int'>
print(bin(x)) #0b10010
print(oct(x)) #0o22
print(hex(x)) #0x12
print(float(x)) #18.0
print(complex(x)) #(18+0j)
x = str(65)
print(x) #65
print(type(x)) #<class 'str'>
print(ord('A')) #65
print(chr(65)) #A
print(list('11234')) #['1', '1', '2', '3', '4']
print(tuple('11234')) #('1', '1', '2', '3', '4')
print(dict(zip('123', 'abc'))) #{'1': 'a', '2': 'b', '3': 'c'}
print(set('11234')) #{'2', '4', '3', '1'}
print(type(3)) #<class 'int'>
print((type([3])) in (list, tuple, set)) #True
print(isinstance(3, int)) #True
print(isinstance([3], (list, tuple, set))) #True
x = str([1, 2, 3])
print(x) #[1, 2, 3]
print(type(x)) #<class 'str'>
print(list(x)) #['[', '1', ',', ' ', '2', ',', ' ', '3', ']']
print(eval(x)) #[1, 2, 3]
print(type(eval(x))) #<class 'list'>
6.最值与求和
内置函数 | 说明 |
---|---|
sum() | 求和 |
max() | 求最大值 |
min() | 求最小值 |
max()和min()函数可以通过参数key指定比较的规则,通过参数default指定找不到最值时的返回值
print(max(['2', '100'])) #2
print(max(['1', '100'], key = len)) #100
print(max([], default = None)) #None
7.排序与逆序
内置函数 | 说明 |
---|---|
sorted() | 将对象排序并返回新列表 |
reversed() | 将对象翻转并返回一个可迭代对象 |
from random import shuffle
x = list(range(11))
shuffle(x)
print(x) #[0, 3, 1, 9, 2, 8, 4, 7, 10, 6, 5]
x = sorted(x) #默认按值升序排列
print(x) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x = sorted(x, key = lambda item: len(str(item)), reverse = True) #转化成字符串后按长度降序排列
print(x) #[10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
x = reversed(x)
print(x) #<list_reverseiterator object at 0x000001C88EBD4FD0>
print(list(x)) #[9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 10]
8.枚举与迭代
内置函数 | 说明 |
---|---|
enumerate() | 返回可迭代对象的每个元素的索引和值,返回的是一个可迭代的enumerate对象 |
print(list(enumerate('abcd'))) #枚举字符串元素 [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
print(list(enumerate(['hello', 'world']))) #枚举列表元素 [(0, 'hello'), (1, 'world')]
print(list(enumerate({'a': 97, 'b': 65}))) #枚举字典元素的键 [(0, 'a'), (1, 'b')]
for index, value in enumerate(range(10, 15)): #枚举range对象元素,用元组返回 (0, 10) (1, 11) (2, 12) (3, 13) (4, 14)
print((index, value), end = ' ')
print('\n')
for index, value in enumerate(range(10, 15)): #枚举range对象元素,用列表返回 [0, 10] [1, 11] [2, 12] [3, 13] [4, 14]
print([index, value], end = ' ')
print('\n')
for index, value in enumerate(range(10, 15)): #枚举range对象元素,用字典返回 {0: 10} {1: 11} {2: 12} {3: 13} {4: 14}
print({index: value}, end = ' ')
print('\n')
9.map()、reduce()、filter()
内置函数 | 说明 |
---|---|
map() | 把一个函数依次作用到序列或迭代器对象的每个元素上,返回一个可迭代的map对象 |
reduce() | 把一个双参函数以累加的方式从左至右依次作用到序列或迭代器对象的每个元素上 |
filter() | 把一个单参函数作用到序列或迭代器对象的每个元素上,返回函数返回值为True的元素构成的可迭代的filter对象 函数为None时返回值为True的元素构成的可迭代的filter对象 |
print(list(map(str, range(5)))) #把range(5)中的对象转化成字符串 ['0', '1', '2', '3', '4']
import random
x = random.randint(1, 1e3) #生成随机数
print(x) #143
print(list(map(int, str(x)))) #提取随机数每个位上的数字[1, 4, 3]
def add5(v):
return v + 5
print(list(map(add5, range(5)))) #把单参函数映射到一个序列上 [5, 6, 7, 8, 9]
def add(x, y):
return x + y
print(list(map(add, range(5), range(5, 10)))) #把双参函数映射到两个序列上 [5, 7, 9, 11, 13]
from functools import reduce
seq = list(range(1, 10))
print(reduce(lambda x, y: x + y, seq)) #45(1 + 2 = 3, 3 + 3 = 6, 6 + 4 = 10, 10 + 5 = 15...)
seq = ['a', '1', '*', ' ']
def func(x):
return x.isalnum()
print(list(filter(func, seq))) #返回字母和数字 ['a', '1']
10.range()
内置函数 | 说明 |
---|---|
range() | 三种用法:range(stop)、range(start, stop)、range(start, stop, step) 返回包含[start, end)内以step为步长的整数的range对象,start默认为0,step默认为1 |
print(list(range(10))) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 到9结束,默认从0开始,步长为1
print(list(range(1,10))) #[1, 2, 3, 4, 5, 6, 7, 8, 9] 从1开始到9结束,默认步长为1
print(list(range(1, 10, 2))) #[1, 3, 5, 7, 9] 从1开始到9结束,步长为2
print(list(range(10, 1, -2))) #[10, 8, 6, 4, 2] 从10开始到2结束,步长为-2
11.zip()
map相当于拉链函数(拉开),zip相当于压缩函数(拉合)
内置函数 | 说明 |
---|---|
zip() | 把多个可迭代对象中的元素压缩到一起,返回可迭代的zip对象,其中的每个元素都是原来的多个可迭代对象对应位置上的元素所构成的元组 |
x = zip('abcd', [1, 2, 3, 4])
y = zip('abcd', [1, 2, 3]) #不等长以短的为准
z = zip(range(5)
print(list(x)) #[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
print(list(y)) #[('a', 1), ('b', 2), ('c', 3)]
print(list(z)) #[(0,), (1,), (2,), (3,), (4,)]
12.关键字
特点:只允许用来表达特定的含义
查看:
import keyword
print(keyword.kwlist)
三、Python序列结构
Python序列概述
有序与无序 | |
---|---|
有序序列 | 列表、元组、字符串 range、zip、map、enumerate等 |
无序序列 | 字典、集合 |
可变与不可变 | |
---|---|
可变序列 | 列表、字典、集合 |
不可变序列 | 元组、字符串 range、zip、map、enumerate等 |
列表、元组、字典、集合的相关性质
列表 | 元组 | 字典 | 集合 | |
---|---|---|---|---|
类型名 | list | tuple | dict | set |
定界符 | [] | () | {} | {} |
是否可变 | 是 | 否 | 是 | 是 |
是否有序 | 是 | 是 | 否 | 否 |
是否支持下标 | 是,序号作下标 | 是,序号作下标 | 是,键作下标 | 否 |
元素分隔符 | , | , | , | , |
元素形式的要求 | 无 | 无 | 键:值 | 必须可哈希 |
对元素值的要求 | 无 | 无 | 键必须可哈希 | 必须可哈希 |
元素是否可重复 | 是 | 是 | 键不允许重复,值可以重复 | 否 |
元素查找速度 | 慢 | 慢 | 快 | 快 |
增删元素速度 | 尾部快,其他位置慢 | 不允许 | 快 | 快 |
1.列表与列表推导式
(1)列表的创建与删除
①用[]创建
l = []
print(l) #[]
l = [1, 2, 3]
print(l) #[1, 2, 3]
②用list()创建
l = list()
print(l) #[]
l = list(range(10)) #range对象转列表
print(l) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
l = list('hello world') #字符串对象转列表
print(l) #['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
l = list((1, 2, 3)) #元组对象转列表
print(l) #[1, 2, 3]
l = list({1, 2, 3}) #集合对象转列表
print(l) #[1, 2, 3]
l = list({'a': 1, 'b': 2, 'c': 3}) #字典的键转列表
print(l) #['a', 'b', 'c']
l = list({'a': 1, 'b': 2, 'c': 3}.keys()) #字典的键转列表
print(l) #['a', 'b', 'c']
l = list({'a': 1, 'b': 2, 'c': 3}.items()) #字典的键值对转列表
print(l) #[('a', 1), ('b', 2), ('c', 3)]
l = list({'a': 1, 'b': 2, 'c': 3}.values()) #字典的值转列表
print(l) #[1, 2, 3]
③用del删除
#用del删除
l = ['a', 'b', 'c']
del l
#print(l) 抛出异常
(2)列表元素访问
l = ["a", "b", "c"]
print(l[0]) #正索引从0开始,输出a
print(l[-1]) #负索引从-1开始,输出c
(3)列表常用方法
方法 | 说明 |
---|---|
append() | 在列表尾加一个元素 |
insert() | 在列表任意位置插入一个元素 |
extend() | 在列表尾加一个列表 |
pop() | 删除并返回指定位置上的元素,默认为最后一个 |
remove() | 删除列表首个与指定值相等的元素 |
count() | 返回指定元素出现的次数 |
index() | 返回指定元素首次出现的位置 |
sort() | 将列表元素按指定规则排序 |
reverse() | 将列表翻转 |
①append()、insert()、extend()
l = [1, 2, 3]
print(l) #[1, 2, 3]
l.append(4) #在列表尾加4
print(l) #[1, 2, 3, 4]
l.insert(0, 0) #在列表下标为0的位置加0
print(l) #[0, 1, 2, 3, 4]
l.extend([5, 6, 7]) #在列表尾加[5, 6, 7]
print(l) #[0, 1, 2, 3, 4, 5, 6, 7]
②pop()、remove()
l = [1, 2, 3, 1, 2, 3]
print(l.pop()) #3 不指定位置删除尾部元素并返回
print(l) #[1, 2, 3, 1, 2]
print(l.pop(0)) #1 删除下标为0的元素并返回
print(l) #[2, 3, 1, 2]
l.remove(2) #删除首个值为2的元素
print(l) #[3, 1, 2]
del l[2] #删除下标为2的元素
print(l) #[3, 1]
③count()、index()
l = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
print(l.count(3)) #3 返回3出现的次数
print(l.count(5)) #指定元素不存在返回0
print(l.index(3)) #3 返回3首次出现的下标
#print(l.index(5)) #指定元素不存在抛出异常
④sort()、reverse()
l = list(range(11))
import random
random.shuffle(l)
print(l) #[5, 8, 2, 0, 6, 9, 3, 1, 4, 10, 7]
l.sort(key = lambda item: len(str(item)), reverse = True) #转换成字符串后按长度降序排列,10的长度为2,其余长度为1
print(l) #[10, 5, 8, 2, 0, 6, 9, 3, 1, 4, 7]
l.sort(key = str) #转换成字符串后升序排列
print(l) #[0, 1, 10, 2, 3, 4, 5, 6, 7, 8, 9],字符串'10'的第一个字符'1'小于'2',因此10排在2的前面
l.sort() #默认按数值大小升序排列
print(l) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
l.reverse() #翻转
print(l) #[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
#sort()是方法,sorted()是函数
print(sorted([1, 3, 2])) #[1, 2, 3]
print(sorted([1, 3, 2], reverse = False)) #[1, 2, 3]
print(sorted([1, 3, 2], reverse = True)) #[3, 2, 1]
#函数reversed()返回的不是列表
print(reversed([1, 3, 2])) #<list_reverseiterator object at 0x000001DC68CFDFA0>
print(list(reversed([1, 3, 2]))) #[2, 3, 1]
(4)列表对象支持的运算符
运算符 | 说明 |
---|---|
+ | 连接两个列表,+返回新列表,+=原地操作 |
* | 重复列表,*返回新列表,*=原地操作 |
in | 判断列表中是否存在某个元素 |
>、<、== | 判断列表中对应位置上的元素的大小关系 |
l = [1, 2, 3]
print(id(l)) #2155684973632
l = l + [4]
print(l) #[1, 2, 3, 4]
print(id(l)) #2155685255872 内存地址改变
l += [5]
print(l) #[1, 2, 3, 4, 5]
print(id(l)) #2155685255872 内存地址不变
l = [1, 2, 3]
print(id(l)) #2630941822016
l = l * 2
print(l) #[1, 2, 3, 1, 2, 3]
print(id(l)) #2630941819520 内存地址改变
l *= 2
print(l) #[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
print(id(l)) #2630941819520 内存地址不变
print(3 in [1, 2, 3]) #True
print([1, 2, 4] > [1, 2, 3, 4]) #True,逐个位置比较直到比出大小为止
(5)内置函数对列表的操作
内置函数 | 说明 |
---|---|
max()/min() | 返回列表中的最大值/最小值 |
sum() | 返回列表中所有元素的和 |
len() | 返回列表中元素的个数 |
zip() | 将多个列表的元素重新组合成元组并返回这些元组的zip对象 |
enumerate() | 返回包含列表元素的索引和值的enumerate对象 |
all() | 判断列表中是否所有的元素都等价于True |
any() | 判断列表中是否存在等价于True的元素 |
l = list(range(11))
import random
random.shuffle(l)
print(l) #[7, 10, 3, 1, 2, 0, 6, 4, 5, 9, 8]
print(all(l)) #False,不全为非0元素
print(any(l)) #True,存在不为0的元素
print(max(l)) #10
print(min(l)) #0
print(max(l, key = str)) #9
print(sum(l)) #55
print(len(l)) #11
print(list(zip(l, ['a'] * 11))) #[(7, 'a'), (10, 'a'), (3, 'a'), (1, 'a'), (2, 'a'), (0, 'a'), (6, 'a'), (4, 'a'), (5, 'a'), (9, 'a'), (8, 'a')]
print(list(enumerate(l))) #[(0, 7), (1, 10), (2, 3), (3, 1), (4, 2), (5, 0), (6, 6), (7, 4), (8, 5), (9, 9), (10, 8)]
(6)列表推导式
①语法格式
[expression for expr1 in sequence1 if condition1
for expr2 in sequence1 if condition2
...
for exprN in sequenceN if conditionN]
②利用列表推导式使循环更加简洁
l = [x * x for x in range(10)]
print(l) #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
#等价于
l = []
for x in range(10):
l.append(x * x)
print(l) #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
③利用列表推导式实现嵌套列表的平铺
vec = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
res = [num for elem in vec for num in elem]
print(res) #[1, 2, 3, 4, 5, 6, 7, 8, 9]
#等价于
vec = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
res = []
for elem in vec:
for num in elem:
res.append(num)
print(res) #[1, 2, 3, 4, 5, 6, 7, 8, 9]
④在列表推导式中用if过滤不和条件的元素
l = [-3, -2, -1, 0, 1, 2, 3]
print([i for i in l if i > 0]) #[1, 2, 3]
(7)切片
①语法格式
[start: end: step]即[起点: 终点: 步长]
start为0时可省略,end为列表长度时可省略,step为1时连同它前面的冒号也可以省略
step>0表示正向切片,start<end,切出的列表不含end
step<0表示反向切片,start>end,切出的列表不含start
②使用切片获取列表部分元素
l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(l[::]) #[1, 2, 3, 4, 5, 6, 7, 8, 9]
print(l[::-1]) #[9, 8, 7, 6, 5, 4, 3, 2, 1]
print(l[1: 9: 2]) #[2, 4, 6, 8]
print(l[9: 1: -2]) #[9, 7, 5, 3]
③使用切片增加列表元素
l = [3, 5, 6]
print(l) #[3, 5, 6]
l[len(l):] = [7] #在尾部加
print(l) #[3, 5, 6, 7]
l[: 0] = [1, 2] #在头部加
print(l) #[1, 2, 3, 5, 6, 7]
l[3: 3] = [4] #在中间加
print(l) #[1, 2, 3, 4, 5, 6, 7]
④使用切片替换和修改列表中的元素
l = [3, 5, 7, 9]
print(l) #[3, 5, 7, 9]
l[:3] = [1, 2, 3] #替换前3项
print(l) #[1, 2, 3, 9]
l[3:] = [4, 5, 6] #替换第3项以后的项
print(l) #[1, 2, 3, 4, 5, 6]
l[::2] = ['a', 'b', 'c'] #隔一个修改一个
print(l) #['a', 2, 'b', 4, 'c', 6]
⑤使用切片删除列表中的元素
l = [3, 5, 7, 9]
print(l) #[3, 5, 7, 9]
l[:3] = [] #删除前3项
print(l) #[9]
l = [3, 5, 7, 9]
print(l) #[3, 5, 7, 9]
del l[:3] #删除前3项
print(l) #[9]
l = [3, 5, 7, 9]
print(l) #[3, 5, 7, 9]
del l[::2] #隔一个删一个
print(l) #[5, 9]
2.元组和生成器推导式
(1)元组的创建与元素访问
①用()创建
t = ()
print(t) #()
t = (1, 2, 3)
print(t) #(1, 2, 3)
t = (1,) #只有1个元素时要加逗号
print(t) #(1,)
print(type(t)) #<class 'tuple'>
t = (1)
print(t) #1
print(type(t)) #<class 'int'>
②用tuple()创建
t= tuple()
print(t) #()
t = tuple(range(5)) #其他迭代对象转元组
print(t) #(0, 1, 2, 3, 4)
③用索引访问
t = ('a', 'b', 'c')
print(t[0]) #输出a
print(t[-1]) #输出c
(2)元组与列表的异同
同 |
---|
都支持双向索引访问 |
count()、index()方法对两者都适用 |
+、in运算符对两者都适用 |
len()、map()、filter()对两者都适用 |
异 |
---|
元组不可变,可以用索引访问,但不能用索引对元素进行增、删、改的操作 |
元组无append()、extend()、insert()方法,无法直接向元组添加元素 |
元组无pop()、remove()方法,无法直接删除元组中的元素,也不能del某个元素,只能del整个元组 |
元组可以用切片访问,但不能用切片进行增、删、改的操作 |
元组访问速度比列表快 |
用元组传递参数比列表更安全 |
元组可以作字典的键、集合中的元素,但列表不能 |
(3)生成器推导式
生成器推导式与列表推导式类似,但形式上采用()作为定界符,生成器推导式的结果是生成器对象,类似迭代器对象,有惰性求值的特点,即只在需要时生成新元素,比列表推导式效率更高,占用空间更少,适合大数据处理。
访问生成器对象的3种方法:
①根据需要将其转化成列表或元组
②使用生成器对象的___next__()方法或内置函数next()来遍历
③使用for循环来遍历
注意:只能从前往后正向访问,不能再次访问已访问的元素,也不支持下标访问,当所有元素都访问完后,若要再次访问,则需要重新创建生成器对象,enumerate、filter、map、zip等其他迭代器对象也有该特点
g = (i * i for i in range(10)) #创建生成器对象
print(tuple(g)) #(0, 1, 4, 9, 16, 25, 36, 49, 64, 81) 将生成器对象转换成元组输出
print(list(g)) #[] 生成器对象访问了一遍之后就不存在了
g = (i * i for i in range(10)) #创建生成器对象
print(g.__next__()) #0 使用__next__()方法来获取元素
print(next(g)) #1 使用next()函数来获取元素
g = (i * i for i in range(10)) #创建生成器对象
for item in g: #用for循环遍历生成器对象中的元素
print(item, end = ' ')
#0 1 4 9 16 25 36 49 64 81
x = filter(None, range(10))
print(5 in x) #True
print(2 in x) #False 不能再次访问
x = map(str, range(10))
print('0' in x) #True
print('0' in x) #False 访问过的元素不存在
3.字典
字典中的键为数字、字符串、元组等可哈希的数据,不能包含列表、字典、集合等可变的数据
(1)字典的创建
①用{}创建
d = {}
print(d) #{}
d = {1: 'a', 2: 'b', 3: 'c'}
print(d) #{1: 'a', 2: 'b', 3: 'c'}
②用dict()创建
d = dict()
print(d) #{}
keys = ['a', 'b', 'c']
values = [1, 2, 3]
d = dict(zip(keys, values)) #根据已有的数据创建
print(d) #{'a': 1, 'b': 2, 'c': 3}
d = dict(name = 'Tom', age = '18', sex = 'male') #以关键字的形式创建
print(d) #{'name': 'Tom', 'age': '18', 'sex': 'male'}
d = dict.fromkeys(['name', 'age', 'sex']) #以给定内容为键,创建值为空的字典
print(d) #{'name': None, 'age': None, 'sex': None}
(2)字典元素的访问
①用键访问
d = dict(name = 'Tom', age = '18', sex = 'male') #以关键字的形式创建
print(d) #{'name': 'Tom', 'age': '18', 'sex': 'male'}
print(d['age']) #18 指定的键存在返回对应的值
# print(d['address']) #指定的键不存在抛出异常
②用get()方法访问
d = dict(name = 'Tom', age = '18', sex = 'male') #以关键字的形式创建
print(d) #{'name': 'Tom', 'age': '18', 'sex': 'male'}
print(d.get('age')) #18 指定的键存在返回对应的值
print(d.get('address', 'Not exist')) #Not exist,指定的键不存在返回默认的值
(3)元素的增删改
①以指定的键对字典元素进行增或改的操作
d = dict(name = 'Tom', age = '18', sex = 'male') #以关键字的形式创建
print(d) #{'name': 'Tom', 'age': '18', 'sex': 'male'}
d['age'] = 20
print(d) #{'name': 'Tom', 'age': 20, 'sex': 'male'} 指定的键存在则修改
d['address'] = 'Guangzhou'
print(d) #{'name': 'Tom', 'age': 20, 'sex': 'male', 'address': 'Guangzhou'} 指定的键不存在则添加
②用update()方法将另一字典全部的键值对一次性添加到当前字典中,若键重复,则以另一个字典中的值为准
d = dict(name = 'Tom', age = '18', sex = 'male') #以关键字的形式创建
print(d) #{'name': 'Tom', 'age': '18', 'sex': 'male'}
d.update({'age': 20, 'address': 'Guangzhou'}) #修改同时添加
print(d) #{'name': 'Tom', 'age': 20, 'sex': 'male', 'address': 'Guangzhou'}
③用del命令、pop()和popitem()方法删除字典元素
d = dict(name = 'Tom', age = '18', sex = 'male', address = 'Guangzhou') #以关键字的形式创建
print(d) #{'name': 'Tom', 'age': '18', 'sex': 'male', 'address': 'Guangzhou'}
del d['age']
print(d) #{'name': 'Tom', 'sex': 'male', 'address': 'Guangzhou'}
print(d.pop('sex')) #male 删除指定元素并返回
print(d) #{'name': 'Tom', 'address': 'Guangzhou'}
print(d.popitem()) #('address', 'Guangzhou') 随机删除并返回一个元素
print(d) #{'name': 'Tom'}
print(d.popitem()) #('name', 'Tom')
print(d) #{}
print(d.popitem()) #对空字典抛出异常
4.集合
集合中只能包含数字、字符串、元组等可哈希的数据,不能包含列表、字典、集合等可变的数据
(1)集合的创建与删除
①用{}创建
s = {}
print(s) #{}
s = {1, 2, 3}
print(s) #{1, 2, 3}
②用set()创建
s = set()
print(s) #set()
s = set(range(11))
print(s) #{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
s = set([1, 1, 2, 2, 3, 3])
print(s) #{1, 2, 3} 自动去重
(2)集合操作
方法 | 说明 |
---|---|
add() | 向集合添加元素,若该元素已存在则忽略 |
update() | 将另一个集合中的元素合并到当前集合中,自动去除重复元素 |
pop() | 随机删除并返回一个元素,集合为空则抛出异常 |
remove() | 删除集合中指定的元素,指定元素不存在则抛出异常 |
discard() | 删除集合中指定的元素,指定元素不存在则忽略该操作 |
clear() | 清空集合中的所有元素 |
s = {1, 2, 3}
print(s) #{1, 2, 3}
s.add(3)
print(s) #{1, 2, 3} 元素重复则忽略
s.update({3, 4})
print(s) #{1, 2, 3, 4} 元素重复则忽略
print(s.pop()) #1 随机删除并返回一个元素
print(s) #{2, 3, 4}
# s.remove(5) 删除指定元素,指定元素不存在则抛出异常
# print(s)
s.discard(5) #删除指定元素,指定元素不存在则忽略该操作
print(s) #{2, 3, 4}
s.clear()
print(s) #set()
(3)集合运算
a = {1, 2, 4, 5, 6}
b = {1, 3, 5, 7}
print(a | b) #并集{1, 2, 3, 4, 5, 6, 7}
print(a.union(b)) #{1, 2, 3, 4, 5, 6, 7}
print(a & b) #交集{1, 5}
print(a.intersection(b)) #{1, 5}
print(a - b) #差集{2, 4, 6}
print(a.difference(b)) #{2, 4, 6}
print(a ^ b) #对称差集{2, 3, 4, 6, 7}
print(a.symmetric_difference(b)) #{2, 3, 4, 6, 7}
print({1, 2, 3} == {1, 2, 3}) #集合相等True
print({1, 2, 3} <= {1, 2, 3}) #子集True
print({1, 2, 3} < {1, 2, 3}) #真子集False
几种推导式:
返回 | ||
---|---|---|
列表推导式 | [<元素表达式> for <变量> in <迭代对象> if <逻辑条件>] | 列表 |
字典推导式 | {<键值表达式>: <元素表达式> for <变量> in <迭代对象> if <逻辑条件>} | 字典 |
集合推导式 | {<元素表达式> for <变量> in <迭代对象> if <逻辑条件>} | 集合 |
元组生成器推导式 | (<元素表达式> for <变量> in <迭代对象> if <逻辑条件>) | 生成器 |
5.序列解包
(1)使用序列解包对多个变量同时赋值
x, y, z = 1, 2, 3
print(x, y, z) #1 2 3
x, y, z = 'abc' #对字符串进行序列解包
print(x, y, z) #a b c
v = [1, 2, 3]
x, y, z = v #对列表进行序列解包
print(x, y, z) #1 2 3
v = (1, 2, 3)
x, y, z = v #对元组进行序列解包
print(x, y, z) #1 2 3
v = {'a': 1, 'b': 2, 'c': 3}
x, y, z = v.items() #对字典进行序列解包
print(x, y, z) #('a', 1) ('b', 2) ('c', 3)
x, y, z = range(3) #对range对象进行序列解包
print(x, y, z) #0 1 2
x, y, z = map(str, range(3)) #对map对象进行序列解包
print(x, y, z) #0 1 2
x, y, z = iter([1, 2, 3]) #对迭代器对象进行序列解包
print(x, y, z) #1 2 3
(2)使用序列解包遍历多个序列
keys = ['a', 'b', 'c'']
values = [1, 2, 3]
for k, v in zip(keys, values):
print(k, v)
'''
a 1
b 2
c 3
'''
(3)使用序列解包遍历enumberate()返回的迭代对象
x = ['a', 'b', 'c']
for i, v in enumerate(x):
print('The value on {0} is {1}.'.format(i, v))
'''
The value on 0 is a.
The value on 1 is b.
The value on 2 is c.
'''
(4)使用序列解包遍历字典元素
x = {'a': 1, 'b': 2, 'c': 3}
for k, v in x.items():
print(k, v)
'''
a 1
b 2
c 3
'''
四、选择结构与循环结构
1.条件表达式
条件表达式的值除了是False、0(0.0或0j)、None、空列表、空元组、空字典、空集合、空range对象或其他空迭代对象外,均为True
2.选择结构
(1)单分支选择结构
if 表达式:
语句块
x = input('please input two numbers:') #2 1
a, b = map(int, x.split())
print(a, b) #2 1
if a > b:
a, b = b, a
print(a, b) #1 2
(2)双分支选择结构
if 表达式:
语句块1
else:
语句块2
x = input('please input two numbers:') #1 1
a, b = map(int, x.split())
print(a, b) #1 1
if a == b:
print('{0} = {1}'.format(a, b)) #1 = 1
else:
print('{0} != {1}'.format(a, b))
三元运算符
value1 if condition else value2
x = 6 if 5 > 10 else 9
print(x) #9
#等价于
if 5 > 10:
x = 6
else:
x = 9
print(x) #9
(3)多分支选择结构
if 表达式1:
语句块1
elif 表达式2:
语句块2
else:
语句块3
x = input('please input two numbers:') #3 2
a, b = map(int, x.split())
print(a, b) #3 2
if a == b:
print('{0} = {1}'.format(a, b))
elif a < b:
print('{0} < {1}'.format(a, b))
else:
print('{0} > {1}'.format(a, b)) #3 > 2
(4)选择结构的嵌套
if 表达式1:
语句块1
if 表达式2:
语句块2
else:
if 表达式3:
语句块3
else:
语句块4
def func(score):
degree = 'DCBAAE'
if score > 100 or score < 0:
return 'wrong score!'
else:
index = (score - 60) // 10
if index >= 0:
return degree[index]
else:
return degree[-1]
score = int(input('please in put the score:')) #95
res = func(score)
print(res) #A
3.循环结构
循环结构主要包括for循环和while循环,for循环一般用于循环次数确定的循环,while循环一般用于循环次数不确定的循环。
对于有else子句的循环结构,若循环由于条件表达式不成立或遍历结束而自然结束时执行else结构中的语句,若循环由于执行了break语句而提前结束则不会执行else结构中的语句
(1)for循环和while循环
for 取值 in 序列或迭代对象:
循环体
[else:
else子句代码块]
while 条件表达式:
循环体
[else:
else子句代码块]
for i in range(1, 101): #输出1~100之间能被8和3整除的数
if i % 8== 0 and i % 3 == 0:
print(i)
'''
24
48
72
96
'''
i = 1
while i <= 100: #输出1~100之间能被8和3整除的数
if i % 8== 0 and i % 3 == 0:
print(i)
i = i + 1
'''
24
48
72
96
'''
(2)break和continue语句
break语句提前结束其所属的循环,continue语句提前结束本轮循环,进入其所属循环的下一轮循环
for n in range(100, 1, -1): #计算小于100的最大素数
if n % 2 == 0:
continue #若n % 2 == 0,continue后的语句不执行,进入下一轮循环
for i in range(3, int(n ** 0.5) + 1, 2):
if n % i == 0:
break #提前结束内循环
else:
print(n) #97
break #提前结束外循环
五、函数
1.函数定义与调用的基本方法
(1)定义
def 函数名([参数列表]):
函数体
注意:
①函数形参不用声明类型,也不用指定函数返回值的类型
②无参函数的函数名后的"()"也要保留
③’’()“后要有”:"
④函数体对于def要有缩进
⑤函数可嵌套
def fib(n): #定义生成n以内的斐波那契数列的函数,n为形参
a, b = 1, 1
while a < n:
print(a, end = ' ')
a, b = b, a + b
print()
fib(1000) #调用函数,n为实参
#1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
2.函数递归调用
函数递归调用是指:函数不断调用自己,直到满足某个条件时不再调用,然后一层一层地返回直到函数第一次调用的位置
#使用递归法对函数进行因式分解
from random import randint
def factor(num, fac = []):
for i in range(2, int(num ** 0.5) + 1): #从2开始查找
if num % i == 0:
fac.append(i) #找到一个因数
factor(num // i, fac) #对商再次进行分解
break #跳出循环,逐层返回
else:
fac.append(num) #不可分解了,本身也是一个因数
facs = [] #存放因数的列表
n = randint(2, 10 ** 8) #n为2到10的8次方的一个随机数
factor(n, facs) #调用函数求得所有的因数
result = '*'.join(map(str, facs)) #在每个因数之间加一个'*'得到一个字符串'a*b*c...'
if n == eval(result): #eval对字符串求值,即计算所有因数的积
print(n, '=' + result)
#52035082 =2*11*11*53*4057
3.函数参数
函数参数 | 说明 |
---|---|
位置参数 | 调用函数时实参和形参的顺序和数量必须一致 |
默认值参数 | 在调用带默认值参数的函数时,可选择是否为默认值参数传参 在定义带默认值参数的函数时,带默认值的参数要放在()最右边 |
关键参数 | 调用函数时按参数名传参,实参和形参的顺序可不一致 |
可变长度参数 | *parameter接收多个位置参数并存放在一个元组中 **parameter接收多个关键参数并存放在一个字典中 |
def demo(a, b, c):
print(a, b, c)
demo(3, 4, 5) #3 4 5
def demo(a, b, c = 2):
print(a, b, c)
demo(3, 4) #3 4 2 使用默认值参数
demo(3, 4, 5) #3 4 5 不使用默认值参数
demo(a = 2, b = 4, c = 6) #2 4 6 关键参数
def demo(*p):
print(p)
demo(1, 2, 3) #(1, 2, 3)
def demo(**p):
for item in p.items():
print(item, end = ' ')
demo(x = 1, y = 2, z = 3) #('x', 1) ('y', 2) ('z', 3)
4.传递参数时的序列解包
传递参数时,可在实参序列前加’*'将其解包,然后传递给多个单变量形参(相当于位置传参)
若函数实参为字典,可在前面加’**'将其解包,然后传递给多个单变量形参(相当于关键参数传参)
def demo(a, b, c):
print(a, b, c)
l = [1, 2, 3]
demo(*l) #1 2 3
t = (1, 2, 3)
demo(*t) #1 2 3
d = {'a': 1, 'b': 2, 'c': 3}
demo(**d) #1 2 3
demo(*d.values()) #1 2 3
5.变量作用域
变量的作用域指变量起作用的代码范围
全局变量指在函数外部定义的变量,局部变量指在函数内部定义的变量,当函数执行结束后局部变量自动删除,不再使用,由于局部变量的引用比全局变量快,应优先考虑使用
(1)全局变量与局部变量的作用范围不同
x = "Monday"
def myfunc():
x = "Tuesday"
print("Today is " + x)
myfunc() #输出Today is Tuesday,局部变量只作用于函数内部,且函数内的局部变量与全局变量同名时,以局部变量为准
print("Today is" + x) #输出Today is Monday,全局变量作用于全体函数
(2)全局关键字global可以将局部变量转化成全局变量
x = "Monday"
def myfunc():
global x = "Tuesday" //用全局关键字将局部变量转化成全局变量
print("Today is " + x)
myfunc() #输出Today is Tuesday,
print("Today is" + x) #输出Today is Tuesday
6.lamba表达式
lamba表达式用于声明匿名函数,即没有函数名的临时使用的小函数,也可声明具名函数
lamba表达式可只含一个表达式,表达式的计算结果作为函数的返回值,lamba表达式中不可包含复合语句,但可以调用其他函数
f = lambda x, y, z: x + y + z #给lamba表达式取名,即可像函数一样调用
print(f(1, 2, 3)) #6
l = [1, 2, 3, 4, 5]
print(list(map(lambda x: x + 10, l))) #[11, 12, 13, 14, 15] lamba表达式可做map()函数中的函数
l = [20, 2, 200, 2000]
l.sort(key = lambda x: len(str(x))) #lamba表达式可做sort()方法中的key函数
print(l) #[2, 20, 200, 2000]
7.生成器函数
生成器函数:包含yield语句的可用于创建生成器对象的函数称为生成器函数
yield语句与return语句的异同
同 | 异 |
---|---|
都是用来从函数中返回值 | return语句一旦执行就会结束函数的运行 yield语句执行后会返回一个值并暂停后面代码的执行,等下一次索要返回值时恢复执行 |
生成器函数索要返回值的方法:
①生成器对象的__next__()方法
②内置函数next()
③for循环
生成器具有惰性求值的特点,适合大数据处理
#编写并使用能够生成斐波那契数列的生成器函数
def f():
a, b = 1, 1
while True:
yield a
a, b = b, a + b
a = f() #创建生成器对象
print(a.__next__()) #返回一个值 1
print(next(a)) #返回下一个值 1
for item in f(): #返回斐波那契数列第一个大于100的元素 144
if item > 100:
print(item)
break
a = f() #创建生成器对象
for i in range(10): #打印输出斐波那契数列的前十个元素
print(a.__next__(), end = ' ')
#1 1 2 3 5 8 13 21 34 55
六、面向对象的程序设计
1.类的定义和使用
class Car(object): #定义一个叫Car的类,派生自object类
def info(self): #定义成员方法info()
print("This is a car.")
car = Car() #实例化对象
car.info() #调用对象的成员方法 This is a car.
2.数据成员与成员方法
数据成员:创建类时用变量形式表示对象特征的成员
成员方法:创建类时用函数形式表示对象行为的成员
数据成员和成员方法统称类的成员
(1)私有成员与公有成员
私有成员:在类的外部不可直接访问,但Python中没有对私有成员提供严格的访问保护机制,在外部程序可以通过"对象名._类名__xxx"访问私有成员,不过这样会破坏类的封装性,不建议使用
公有成员:可在类的内部访问,也可在外部程序使用
以下划线开头的变量名和方法有特殊含义:
_xxx:受保护成员,类及它的子类都可以访问
__xxx__:系统定义的特殊成员
__xxx:私有成员,只有类能访问,其子类也不能访问
class A:
def __init__(self, value1 = 1, value2 = 2):
self._value1 = value1 #公有成员
self.__value2 = value2 #私有成员
a = A()
print(a._value1) #1 直接访问共有成员
print(a._A__value2) #2 通过"对象名._类名__xxx"的形式访问私有成员
(2)数据成员
属于对象的数据成员:一般在__init__()中定义,也可在其他成员方法中定义,在定义和实例化方法中访问数据成员时以self作为前缀
self参数代表当前的对象,在实例化方法中访问实例成员需要以self为前缀,但在外部通过对象名调用对象的方法时不用传递该参数,因为通过对象调用公有方法时会把对象隐式绑定到self上
属于类的数据成员:该数据成员为该类所有对象所共享的,一般不在任何一个成员方法中定义
利用类数据成员的共享性,可以实时获得该类的对象数量,并可以控制该类可以创建的对象的最大数量
(3)成员方法
class Root:
__total = 0
def __init__(self, v): #构造方法
self.__value = v
Root.__total += 1
def show(self): #普通实例方法
print('self.__value', self.__value)
print('Root.__total', Root.__total)
@classmethod #修饰器 声明类方法
def clsssShowTotal(cls): #类方法
print(cls.__total)
@staticmethod #修饰器 声明静态方法
def staticShowTotal(): #静态方法
print(Root.__total)
r = Root(3)
r.clsssShowTotal() #通过对象调用类方法 1
r.staticShowTotal() #通过对象调用静态方法 1
r.show() #通过对象调用实例方法
'''
self.__value 3
Root.__total 1
'''
rr = Root(5)
Root.clsssShowTotal() #通过类名调用类方法 2
Root.staticShowTotal() #通过类名调用静态方法 2
Root.show(r) #通过类名和对象名调用实例方法
'''
self.__value 3
Root.__total 2
'''
Root.show(rr) #通过类名和对象名调用实例方法
'''
self.__value 5
Root.__total 2
'''
(4)属性
可以指定类的读、写、删除的属性
class Test:
def __init__(self, value):
self.__value = value
def __get(self): #可读
return self.__value
def __set(self, v): #可修改
self.__value = v
def __del(self):
del self.__value
value = property(__get, __set, __del) #value可以进行读,修改,删除的操作
def show(self):
print(self.__value)
t = Test(3)
t.show() #3
print(t.value) #读 3
t.value = 5 #修改
t.show() #5
# del t.value
# t.show()
3.继承
在继承关系中,已有的、已设计好的类称父类或基类,新设计的类称子类或派生类,派生类可以继承基类类的公有成员,但不能继承其私有成员,若要在派生类调用基类的方法,可以用函数super()或"基类名.方法名()"来实现
Python支持多继承,若父类中有相同的方法名,子类使用时没有指定父类名,则按从左到右的顺序搜索父类中的该方法
4.特殊方法
Python中有大量的特殊方法,较常见的有构造函数和析构函数
特殊方法 | 说明 |
---|---|
构造函数_int_() | 为数据成员设置初值或其他初始化工作 |
析构函数_del_() | 释放对象占用的资源 |
七、字符串
1.字符串简介
字符串以单引号、双引号作界定符,界定符之间可嵌套
x = 'Hello, World'
x = '''Life is short,
I learn python.'''
x = "Hello, World"
x = """Life is short,
I learn python."""
x = """Tom said: 'Let's go.'"""
print(x) #输出Tom said: 'Let's go.'
x = '''Tom said: "Let's go"'''
print(x) #输出Tom said: "Let's go"
字符串除了支持序列的通用方法(包括双向索引、比较大小、计算长度、元素访问、切片、成员测试等操作)外,还有一些特有的操作,如字符串格式化、查找、替换、排版等
字符串属于不可变序列,不能直接进行增、删、改的操作,凡是涉及修改字符串的操作都是返回一个新的字符串,而不是在原字符串的基础上操作
2.字符串编码
编码 | 说明 |
---|---|
ASCII | 美国标准信息交换码,用一个字节表示字符(10个数字,26个大小写字母以及一些符号) |
GB2312 | 我国制定的中文编码,用一个字节表示英文,两个字节表示中文 |
UTF-8 | 对全世界所有国家需要用到的字符进行了编码,用一个字节表示英文,三个字节表示中文,部分语言的符号采用二或四个字节 |
无论是数字、英文还是中文,在统计字符串长度时都当成一个字符
3.转义字符
转义字符 | 含义 |
---|---|
\b | 退格 |
\f | 换页 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\\ | \ |
\’ | ’ |
\" | " |
\ooo | 三位八进制数对应的字符 |
\xhh | 二位十六进制数对应的字符 |
\uhhhh | 四位十六进制数表示的Unicode字符 |
在字符串前面加上r或R表示原始字符串,其中的所有字符都表示原始的含义而不会进行任何的转义
4.格式化
(1)用%进行格式化
常用格式字符
格式字符 | 说明 |
---|---|
%s | 字符串(采用str()的显示) |
%r | 字符串(采用repr()的显示) |
%c | 单个字符 |
%d,%i | 十进制整数 |
%o | 八进制整数 |
%x | 十六进制整数 |
%e | 指数(基底写e) |
%E | 指数(基底写E) |
%f,%F | 浮点数 |
%g | 指数(e)或浮点数(根据显示长度) |
%G | 指数(E)或浮点数(根据显示长度) |
%% | 百分号 |
x = 123
print("%o" % x) #173
print("%x" % x) #7b
print("%e" % x) #1.230000e+02
print("%f" % x) #123.000000
print("%s" % x) #123
(2)用format()方法格式化
print(1 / 3) #0.3333333333333333
print('{0:.3f}'.format(1 / 3)) #保留三位小数 0.333
print('{0: %}'.format(0.25)) #格式化为百分数 25.000000%
print('The number {0} in hex is: {0: #x}, the number {1} in oct is {1: #o}'.format(5555, 55))
#The number 5555 in hex is: 0x15b3, the number 55 in oct is 0o67
print('The number {1} in hex is: {1: #x}, the number {0} in oct is {0: #o}'.format(5555, 55))
#The number 55 in hex is: 0x37, the number 5555 in oct is 0o12663
(3)格式化的字符串常量
在字符串前加f,含义与format()方法类似
print('My name is {name}, my age is {age}.'.format(name = 'Tom', age = 18))
#My name is Tom, my age is 18.
name = 'Tom'
age = 18
print(f'My name is {name}, my age is {age}.') #My name is Tom, my age is 18.
5.字符串常用方法和操作
方法 | 说明 |
---|---|
find(),rfind() | 查找一个字符串在另一个字符串指定范围(默认为整个字符串)中首次和最后一次出现的位置,若不存在则返回-1 |
index(),rindex() | 查找一个字符串在另一个字符串指定范围(默认为整个字符串)中首次和最后一次出现的位置,若不存在则抛出异常 |
count() | 返回一个字符串在当前字符串中出现的次数 |
split(), rsplit() | 以指定字符为分隔符将原字符串从左到右或从右到左分隔成多个字符串并返回包含分隔结果的列表,可指定最大分隔次数,若最大分隔次数大于可分隔次数则无效,若不指定分隔符,字符串中的任何空白符号都看作分隔符,连续多个空白字符看作一个分隔符 |
partition(),rpartition() | 以指定字符为分隔符将原字符串分隔成分隔符前的字符串,分隔符字符串,分隔符后的字符串,若指定的分隔符不在原字符串中,则返回原字符串和两个空字符串 |
join() | 字符串连接 |
lower() | 返回小写字符串 |
upper() | 返回大写字符串 |
capitialize() | 返回首字母大写的字符串 |
title() | 返回每个单词首字母大写的字符串 |
swapcase() | 返回大小写互换的字符串 |
replace() | 查找替换 |
maketrans() | 生成字符映射表 |
translate() | 根据生成的字符映射表中定义的对应关系转换字符串并替换其中的字符 |
strip() | 删除指定字符 |
rstrip() | 删除字符串右端指定字符 |
lstrip() | 删除字符串左端指定字符 |
strartswith(),endswith() | 判断字符串是否以指定字符开始或结束 |
isalnum(),isalpha(),isdigit(), isspace(),isupper(),islower() | 测试字符串是否为字母或数字,是否为字母,是否为数字,是否为空白字符,是否为大写字母,是否为小写字母 |
center(),ljust(),rjust() | 返回指定宽度的新的字符串,原字符串居中,左对齐或右对齐出现在新字符串中,若指定宽度大于字符串长度,则使用指定的字符(默认为空格)进行填充 |
(1)find(),rfind(),index(),rindex(),count()
fruits = "apple, banana, orange, pear"
print(fruits.find('orange')) #15
print(fruits.find('orange',1, 10)) #不存在返回-1
print(fruits.rfind('a')) #25
print(fruits.index('orange')) #15
#print(fruits.index('orange', 1, 10)) #不存在抛出异常
print(fruits.rindex('a')) #25
print(fruits.count('a')) #6
(2)split(),rsplit(),partition(),rpartition()
fruits = "apple, banana, orange, pear"
print(fruits.split(',')) #['apple', ' banana', ' orange', ' pear']
print(fruits.split(',', 2)) #['apple', ' banana', ' orange, pear']
print(fruits.rsplit(',', maxsplit = 2)) #['apple, banana', ' orange', ' pear']
print(fruits.partition(',')) #('apple', ',', ' banana, orange, pear')
print(fruits.rpartition(',')) #('apple, banana, orange', ',', ' pear')
print(fruits.rpartition('*')) #('', '', 'apple, banana, orange, pear')
fruits = "apple\t\t\tbanana\t\torange\tpear"
print(fruits.split()) #['apple', 'banana', 'orange', 'pear'] 多个连续空白字符看成一个
print(fruits.split('\t')) #['apple', '', '', 'banana', '', 'orange', 'pear']
(3)join()
fruits = ["apple", "banana", "orange", "pear"]
print('.'.join(fruits)) #apple.banana.orange.pear
(4)lower(),upper(),capitialize(),title(),swapcase()
s = "Life is short, I learn Python."
print(s.lower()) #life is short, i learn python.
print(s.upper()) #LIFE IS SHORT, I LEARN PYTHON.
print(s.capitalize()) #Life is short, i learn python.
print(s.title()) #Life Is Short, I Learn Python.
print(s.swapcase()) #lIFE IS SHORT, i LEARN pYTHON.
(5)replace(),maketrans(),translate()
s = "Hello, World"
print(s) #Hello, World
print(s.replace('World', 'Python')) #Hello, Python
table = s.maketrans('o', '*')
print(s.translate(table)) #Hell*, W*rld
(6)strip(),rstrip(),lstrip()
print('aabbaa'.strip('a')) #bb
print('aabbaa'.rstrip('a')) #aabb
print('aabbaa'.lstrip('a')) #bbaa
(7)strartswith(),endswith()
s = 'Hello, World.'
print(s.startswith('He')) #True 检查整个字符串
print(s.startswith('He',1, 5)) #False,检查指定位置
print(s.endswith('.', 2)) #True
(8)isalnum(),isalpha(),isdigit(),isspace(),isupper(),islower()
s = '123abc'
print(s.isalnum()) #True
print(s.isalpha()) #False
print(s.isdigit()) #False
print('ABC'.isupper()) #True
print('abc'.islower()) #True
(9)center(),ljust(),rjust()
s = 'Hello, World.'
print(s.center(20)) # Hello, World.
print(s.center(20, '*')) #***Hello, World.****
print(s.ljust(20, '*')) #Hello, World.*******
print(s.rjust(20, '*')) #*******Hello, World.
6.字符串支持的运算符
运算符 | 说明 |
---|---|
+ | 连接两个字符串 |
* | 字符串重复 |
in | 判断某个字符或字符串是否存在另一个字符串中 |
print('abc' + 'def') #abcdef
print('abc' * 3) #abcabcabc
print('ab' in 'abc') #True
7.适用于字符串的内置函数
eval()把字符串转化成表达式并进行求值
print(eval('3 + 4')) #7
print(eval('3 < 2')) #False
8.字符串切片
可以通过切片读取字符串中的元素,但不能修改
s = 'abcdefg'
print(s[1:6:]) #bcdef
print(s[0: 2] + s[5: 7]) #abfg
9.字符串常量
string模块提供字符串常量
from random import choice
from string import ascii_letters, digits
character = digits + ascii_letters
print(character) #0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
print(choice(character)) #r 随机选一个
10.中英文分词
import jieba
print(list(jieba.cut('黑色星期四'))) #['黑色', '星期四'] 用原始词库进行分词
jieba.add_word('黑色星期四') #增加词条
print(list(jieba.cut('黑色星期四'))) #['黑色星期四']
11.汉字到拼音的转换
模块:pypinyin
lazy_pinyin('文字') 返回全拼,每个文字的拼音都用字符串存放
lazy_pinyin('文字',1) 返回全拼和声调(声调用符号表示)
lazy_pinyin('文字',2) 返回全拼和声调(声调用数字表示)
lazy_pinyin('文字', 3) 返回首字母
pinyin('文字') 返回全拼和声调(声调用符号表示),每个文字的拼音都用列表存放
pinyin('文字', heteronym = True) 返回多音字的所有读音
八、正则表达式
正则表达式:主要用于字符串匹配
1.正则表达式的表示类型
类型 | 表示 | 举例 | 注意 |
---|---|---|---|
raw string 类型(原生字符串类型) | r’text’ | r’[1-9]\d{5}’ 表示邮政编码,如500632 | 原生字符串类型中的’\'不被解释成转义字符串 |
string类型 (字符串类型) | ‘text’ | '[1-9]\\d{5}'表示邮政编码,如500632 | 字符串类型中的’\‘被解释成转义字符串,若不被转义则要在前面再加一个’\’ |
2.正则表达式的语法
正则表达式元字符及其不同的组合来构成
基本:
元字符 | 说明 | 举例 |
---|---|---|
. | 表示任意单个字符 | |
[] | 字符集,匹配位于()内的任意一个字符 | [abc]表示a,b,c |
[^] | 非字符集 | [^abc]表示除a,b,c外的单个字符 |
- | 在[]内表示范围 | [a-z]表示a~z |
* | 表示前一个字符的0次或无限次扩展 | abc*表示ab,abc,abcc… |
+ | 表示前一个字符的1次或无限次扩展 | abc+表示abc,abcc,abccc… |
? | 单独使用表示前一个字符的0次或1次扩展 跟随其他限定符后匹配能搜索到的,尽量短的字符串,而默认是匹配能搜索到的、尽量长的字符串 | abc?表示ab,abc 在’oooo’中,'o+?‘只匹配单个’o’,而’o+‘匹配所有’o’ |
| | 表示左右表达式的任意一个 | abc|def表示abc,def |
{m} | 表示前一个字符的m次扩展 | ab{2}c表示abbc |
{m, n} | 表示前一个字符的m次至n次扩展 | ab{1, 3}c表示abc,abbc,abbbc |
^ | 匹配字符串开头 | ^abc表示abc在一个字符串开头 |
$ | 匹配字符串结尾 | $abc表示abc在一个字符串结尾 |
() | 分组标记,将()内的内容作为整体看待,里面只能用| | (abc)表示abc,(abc|def)表示abc,def |
\ | 表示位于’\'后的为转义符 | |
\num | num为正整数,表示子模式编号 | '(.)\1’匹配两个连续的相同字符 |
\f | 换页符匹配 | |
\n | 换行符匹配 | |
\r | 回车符匹配 | |
\b | 匹配单词头或尾 | |
\B | 与\b相反 | |
\d | 匹配数字,等效于[0-9] | |
\D | 与\d相反 | |
\s | 匹配任何空白字符,等效于[\f\n\r\t\v] | |
\S | 与\s相反 | |
\w | 匹配任何字母、数字及下划线,等效于[A-Za-z0-9] | |
\W | 与\w相反 |
拓展:
语法 | 说明 |
---|---|
(?P) | 为子模式命名 |
(?P = groupname) | 表示之前命名为groupname的子模式 |
(?#…) | 表示注释 |
(?:…) | 匹配但不捕获该匹配的子表达式 |
(?<=…) | 用于正则表达式前,若<=后的内容在字符串中不出现则匹配,但不返回<=后的内容 |
(?=…) | 用于正则表达式后,若=后的内容在字符串不出现则匹配,但不返回=后的内容 |
(?<!..) | 用于正则表达式前,若<!后的内容在字符串中不出现则匹配,但不返回<!后的内容 |
(?!..) | 用于正则表达式后,若!后的内容在字符串不出现则匹配,但不返回!后的内容 |
r’(\w)(?!.*\1)’ :查找字符串中每个字符的最后一次出现
r’(\w)(?=.*\1)’ :查找字符串中所有重复出现的字符
3.Re库主要功能函数
函数 | 说明 |
---|---|
re.search(pattern, string, flag = 0) | 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象 |
re.match(pattern, string, flag = 0) | 从一个字符串的起始位置起匹配正则表达式,返回match对象 |
re.findall(pattern, string, flag = 0) | 搜索字符串,以列表类型返回所有能匹配的子串 |
re.split(pattern, string, maxsplit = 0, flag = 0) | 将一个字符串按正则表达式匹配结果进行分割,返回一个列表 |
re.finditer(pattern, string, flag = 0) | 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素都是match对象 |
re.sub(pattern, repl, string, count = 0, flags = 0) | 在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串 |
pattern:正则表达式的字符串或原生字符串表示
string:待匹配的字符串
flags:正则表达式使用时的控制标记,可用’|'组合
maxsplit:最大分割数(re.split())
repl:替换匹配字符串的字符串(re.sub()
count:匹配的最大替换次数(re.sub())
常用标记 | 说明 |
---|---|
re.I | 忽略正则表达式的大小写 |
re.M | 正则表达式中的^能将待匹配的字符串的每行当作匹配开始 |
re.S | 正则表达式中的.能匹配除换行符以外的所有字符 |
re.L | 支持本地字符集的字符 |
re.U | 匹配Unicode字符 |
re.X | 忽略模式中的空格,并可用#注释 |
(1)re.search(pattern, string, flag = 0)
import re
match = re.search(r'[1-9]\d{5}', 'BIT 100081')
print(match) #<re.Match object; span=(4, 10), match='100081'>
if match:
print(match.group(0)) #100081
(2)re.match(pattern, string, flag = 0)
import re
match = re.match(r'[1-9]\d{5}', 'BIT 100081')
print(match) #None 字符串的第一个位置不能匹配正则表达式,则不能匹配
if match:
print(match.group(0)) #100081
match = re.match(r'[1-9]\d{5}', '100081 BIT')
print(match) #<re.Match object; span=(0, 6), match='100081'>
if match:
print(match.group(0)) #100081
(3)re.findall(pattern, string, flag = 0)
import re
ls = re.findall(r'[1-9]\d{5}', 'BIT 100081 TSU100084')
print(ls) #['100081', '100084']
(3)re.split(pattern, string, maxsplit = 0, flag = 0)
import re
ls = re.split(r'[1-9]\d{5}', 'BIT 100081 TSU100084')
print(ls) #['BIT ', ' TSU', ''] 将所有匹配的字符串去掉,剩余的字符串构成一个列表
ls = re.split(r'[1-9]\d{5}', 'BIT 100081 TSU100084', maxsplit = 1)
print(ls) #['BIT ', ' TSU100084'] 只能去掉一个匹配了的字符串
(5)re.finditer(pattern, string, flag = 0)
import re
for m in re.finditer(r'[1-9]\d{5}', 'BIT 100081 TSU100084'):
if m:
print(m.group(0))
'''
100081
100084 可迭代地获取每次匹配的结果
'''
(6)re.sub(pattern, repl, string, count = 0, flags = 0)
import re
s = re.sub(r'[1-9]\d{5}', ':zipcode', 'BIT 100081 TSU 100084')
print(s) #BIT :zipcode TSU :zipcode
4.直接使用正则表达式模块re处理字符串
import re
text = 'alpha, beta, ..., gamma, delta'
print(re.split('[, .]+', text)) #['alpha', 'beta', 'gamma', 'delta'] 用一个或多个','' ''.'对字符串进行分隔
print(re.findall('[a-zA-Z]+', text)) #['alpha', 'beta', 'gamma', 'delta'] 查找所有单词
text = "It's a very good good idea"
print(re.sub(r'(\b\w+) \1', r'\1', text)) #It's a very good idea 处理重复的单词
text = 'aAa bBb cCc'
print(re.sub('[a-zA-Z]', lambda x: chr(ord(x.group(0)) ^ 32), text)) #AaA BbB CcC 大小写互换
print(re.search('done|quit', 'ddone!')) #<re.Match object; span=(1, 5), match='done'> 匹配成功
print(re.match('done|quit', 'ddone!')) #None 匹配不成功
text = 'a bb ccc ' #删除多余的空格
print(text.strip()) #a bb ccc 删除两侧空格
print(' '.join(re.split('\s+', text.strip()))) #a bb ccc 所有空格被匹配掉,用单个空格连接字母
print(re.sub('\s+', ' ', text.strip())) #a bb ccc 用单个空格替代匹配的空格
text = 'good good study, day day up.'
print(re.findall(r'\bd.+?\b', text)) #['day', 'day'] 返回以d开头的单词,非贪心模式
print(re.findall(r'\bd.+\b', text)) #['day day up'] 返回以d开头的单词,贪心模式
5.match对象
match对象的主要方法
方法 | 说明 |
---|---|
group() | 返回匹配的一个或多个子模式的内容 |
groups() | 返回一个包含匹配的所有子模式内容的元组 |
groupdict() | 返回包含匹配的所有命名子模式内容的字典 |
start() | 返回指定子模式内容的起始位置 |
end() | 返回指定子模式内容的结束位置的前一个位置 |
span() | 返回一个包含指定子模式内容起始位置和结束位置前一个位置的元组 |
import re
m = re.match(r'(\w+) (\w+)', 'Isaac Newton, physics')
print(m.group(0)) #Isaac Newton 返回整个模式的内容
print(m.group(1)) #Isaac 返回第一个子模式的内容
print(m.group(2)) #Newton 返回第二个子模式的内容
print(m.group(1, 2)) #('Isaac', 'Newton') 返回多个子模式的内容
m = re.match(r'(?P<first_name>\w+) (?P<last_name>\w+)', 'Isaac Newton, physics') #将两个子模式命名
print(m.group('first_name')) #Isaac
print(m.group('last_name')) #Newton
print(m.groups()) #('Isaac', 'Newton') 返回包含所有子模式的元组
print(m.groupdict()) #{'first_name': 'Isaac', 'last_name': 'Newton'} 返回包含所有子模式的字典
九、文件内容操作
1.文件的概念和分类
分类 | |
---|---|
文本文件 | 存储常规字符串 |
二进制文件 | 把对象内容以字节串(bytes)进行存储,需要专门的软件进行解码后读取、显示、修改或执行 |
2.文件操作基本知识
基本操作流程:打开创建文件对象->通过该文件对象对文件内容进行读取、写入、删除、修改等操作->关闭并保存文件内容
(1)内置函数open()
open(file, mode = 'r', buffering = -1, encoding = None, errors = None, newline = None, closefd = True, opener = None)
参数 | 说明 |
---|---|
file | 指定被打开的文件名 |
mode | 指定打开文件后的处理方式 |
buffering | 指定读写文件的缓存模式,0表示不缓存,1表示缓存,大于1表示缓冲区大小 |
encoding | 指定对文件进行编码和解码的方式,只适用于文本模式 |
模式 | 说明 |
---|---|
r | 读模式(默认,可省略),若文件不存在则抛出异常 |
w | 写模式,若文件已存在先清空其内容 |
x | 写模式,创建新文件,若文件已存在则抛出异常 |
a | 追加模式,不覆盖文件原有的内容 |
t | 文本模式(默认,可省略) |
b | 二进制模式(可与其他模式组合使用) |
+ | 读写模式(可与其他模式组合使用) |
f1 = open('file1.txt', 'r') #以读模式打开文件
f1.close #关闭文件
(2)文件对象属性与常用方法
方法 | 功能说明 |
---|---|
close() | 把缓冲区的内容写入文件,同时关闭文件,释放文件对象 |
flush() | 把缓冲区的内容写入文件,但不关闭文件 |
read([size]) | 从文本文件中读取size个字符的内容作为结果返回,若省略size则表示读取所有内容 |
readline() | 从文本文件中读取一行内容作为结果返回 |
readlines() | 把文本文件中的每行内容作为一个字符串存入列表,并返回该列表 |
seek(offset[,whence]) | 把文件指针移动到新的字节位置,offset表示相对whence的位置,whence为0表示从文件头开始计算,1表示从当前位置开始计算,2表示从文件尾开始计算 |
tell() | 返回文件指针的当前位置 |
write(s) | 把s的内容写入文件 |
writelines(s) | 把字符串列表写入文本文件,不添加换行符 |
(3)上下文管理语句with
with语句的作用:无论因什么原因跳出with块,总能保证文件被正确关闭,并且在代码块执行完毕后自动还原进入该代码块时的上下文
with open(filename, mode, encoding) as fp:
#写通过文件对象fp读写文件内容的语句
s = 'Hello, world!'
with open('sample.txt', 'w') as fp: #默认使用cp936编码
fp.write(s)
with open('sample.txt') as fp:
print(fp.read()) #Hello, world!
with open('sample.txt') as fp:
for line in fp: #文件对象可迭代
print(line) #Hello, world!
3.结构化文件
(1)流式文件.csv——纯文本文件,以","为分隔符
值没有类型,所有的值均为字符串
每一行都有相同的·列数,第一行是标题
每一项没有固定宽度,广泛用于大数据存储
(2)文件读取——reader()
re = csv.reader()
reader():接受一个迭代器对象(如csv文件),返回一个生成器,解析出内容
DictReader():与reader()类似,但返回的每一个单元格放在一个元组的值内
(3)文件写操作——writer()
wf = csv.writer()
w = csv.Dictwriter() 字典写入
w.writerow(rows) 写入行
w.writeheader() 写入表头
python常用的序列化模块:struct,pickle,shelve,marshal
十、文件与文件夹操作
1.os模块
方法 | 功能说明 |
---|---|
chdir(path) | 把path设为当前工作目录 |
curdir | 当前文件夹 |
environ | 包含系统环境变量和值的字典 |
extsep | 当前操作系统所使用的文件拓展名分隔符 |
get_exec_path() | 返回可执行文件的搜索路径 |
getcwd() | 返回当前的工作目录 |
listdir(path) | 返回path目录下的文件和目录列表 |
remove(path) | 删除指定的文件,要求用户有删除文件的权限,且文件没有只读或其他特殊属性 |
rename(src, dst) | 重命名文件或目录,可以实现文件的移动,若目标文件已存在则抛出异常,不能跨磁盘或分区 |
replace(old, new) | 重命名文件或目录,若目标文件已存在则覆盖,不能跨磁盘或分区 |
scandir(path = ‘.’) | 返回包含指定文件夹中所有DirEntry对象的迭代对象,遍历文件夹时比listdir()更高效 |
sep | 当前操作系统所使用的路径分隔符 |
startfile(filepath[, operation]) | 使用关联的应用程序打开指定文件或启动指定应用程序 |
system() | 启动外部程序 |
2.os.path模块
方法 | 功能说明 |
---|---|
abspath(path) | 返回给定路径的绝对路径 |
basename(path) | 返回指定路径的最后一个组成部分 |
commonpath(paths) | 返回给定的多个路径的最长公共路径 |
commonprefix(paths) | 返回给定的多个路径的最长公共前缀 |
dirname§ | 返回给定路径的文件夹部分 |
exists(path) | 判断文件是否存在 |
getatime(filename) | 返回文件的最后访问时间 |
getctime(filename) | 返回文件的创建时间 |
getmtime(filename) | 返回文件的最后修改时间 |
getsize(filename) | 返回文件的大小 |
isabs(path) | 判断path是否为绝对路径 |
isdir(path) | 判断path是否为文件夹 |
isfile(path) | 判断path是否为文件 |
join(path, *paths) | 连接两个或多个path |
realpath(path) | 返回给定路径的绝对路径 |
samefile(f1, f2) | 测试f1,f2两个路径是否引用同一文件 |
split(path) | 以路径的最后一个斜线为分隔符把路径分为两部分并以元组的形式返回 |
splitext(path) | 从路径中分隔文件的拓展名 |
splitdrive(path) | 从路径中分隔驱动器的名称 |
#使用递归法遍历指定文件下所有的子目录和文件
from os import listdir
from os.path import join, isfile, isdir
def listDirDepthFirst(directory): #深度优先遍历文件夹
for sunPath in listdir(directory):
path = join(directory, sunPath)
if isfile(path): #如果是文件,则直接输出文件名
print(path)
elif isdir(path): #如果是文件夹,则输出文件夹名,然后递归遍历文件夹
print(path)
listDirDepthFirst(path)
十一、异常处理结构
1.异常的概念与表现形式
异常:程序运行时引发的错误
引发错误的原因:除零,下标越界,文件不存在,网络异常,类型错误,名字错误,字典键错误,磁盘空间不足等
2.异常处理结构
(1)try…except
#只收数字不接收其他类型的数据
while True:
x = input('Please input:')
try:
x = int(x)
print('You have input {0}'.format(x))
break
except Exception as e:#输入不是数字时执行的代码
print('Error')
(2)try…except…else…
#只收数字不接收其他类型的数据
while True:
x = input('Please input:')
try:
x = int(x)
except Exception as e: #输入不是数字时执行的代码
print('Error')
else:
print('You have input {0}'.format(x))
break
(3)try…except…finally…
#读取只写有数字的文件
filename = input('请输入文件名')
try: #尝试打开文件
fp = open(filename)
try: #尝试读取文件
print(int(fp.read()))
except: #文件内容不正确时执行
print('文件内容格式不正确')
finally: #不管文件内容正不正确都要关闭
fp.close()
except: #文件不存在时执行
print('文件不存在')
(4)可以捕捉多种异常的异常处理结构
try:
x = float(input('请输入被除数'))
y = float(input('请输入除数'))
z = x / y
except ZeroDivisionError:
print('除数不能为0')
except ValueError:
print('被除数和除数都应为数值')
except NameError:
print('变量不存在')
else:
print(x, '/', y, '=', z)
3.断言语句和上下文管理语句
语句 | 说明 |
---|---|
断言语句assert | 若满足arrest语句的条件则继续执行下面的代码,否则抛出异常 |
上下文管理语句with | 无论因什么原因跳出with块,总能保证文件被正确关闭,并且在代码块执行完毕后自动还原进入该代码块时的上下文 |
a = 3
b = 5
assert a == b, 'a must be equal to b' #AssertionError: a must be equal to b
十二、tkinker
(1)组件布局
①按钮:Button().pack(位置)
②标签:Label(放置组件,标签文本).pack(位置)
③输入框:Entry(放置组件).pack(位置)
④组件布局:place(x, y)——初始点位置
(2)事件处理机制
①定义事件处理函数
def printEvent():
{
函数体
}
②将处理函数与组件绑定
组件.blind(动作,函数)
十三、网络爬虫入门与应用
1.html基础
(1)h标签
表示标题,h1到h6表示不同级别的标题,h1级别的标题字体最大,h6级别的标题字体最小
<h1>一级标题</h1>
<h2>二级标题</n2>
<h3>二级标题</h3>
(2)p标签
表示段落
<p>这是一个段落</p>
(3)a标签
表示超链接,用href属性指定链接地址和页面上显示的文本
<a href = "https://www.baidu.com/">百度一下,你就知道</a>
(4)img标签
显示图像,用src属性指定图片文件地址,可以是本地文件,也可以是网络上的图片
<img src = "https://t7.baidu.com/it/u=2291349828,4144427007&fm=193&f=GIF" width = "845" height = "1200"/>
(5)table、tr、td标签
table标签用来创建表格,tr用来创建行,td用来创建单元格
<table border = "1">
<tr>
<td>第一行第一列</td>
<td>第一行第二列</td>
</tr>
<tr>
<td>第二行第一列</td>
<td>第二行第二列</td>
</tr>
</table>
(6)ul,ol,li标签
ul标签用来创建无序列表,ol标签用来创建有序列表,li标签用来创建其中的列表项
<ul id = "colors" name = "myColor">
<li>红色</li>
<li>绿色</li>
<li>蓝色</li>
</ul>
(7)div标签
div标签用来创建一个块,可包含其他标签
<div id = "yellowDiv" style = "background-color:yellow;border:#FF0000 1pxsolid;">
<ol>
<li>红色</li>
<li>绿色</li>
<li>蓝色</li>
</ol>
</div>
2.urllib爬虫
爬虫:按照一定规则,自动保存网页中信息的程序
例如:利用urllib爬取公众号文章中的图片
①确定公众号文章地址:
https://mp.weixin.qq.com/s/TH6Z5OlKNE50ljTHlrGjUg
②在浏览器中打开,查看页面源代码,找到图片链接格式
<meta property="og:image" content="http://mmbiz.qpic.cn/mmbiz_jpg/1KichGsxpq6oxSGMG5H6V7v5W0Sz2ld2dtIlfqy4KdQV5yUKIhPOJQ3ztxyjb79Pxv29HbVibbmYhdyNiatpAia3AQ/0?wx_fmt=jpeg" />
链接为:
http://mmbiz.qpic.cn/mmbiz_jpg/1KichGsxpq6oxSGMG5H6V7v5W0Sz2ld2dtIlfqy4KdQV5yUKIhPOJQ3ztxyjb79Pxv29HbVibbmYhdyNiatpAia3AQ/0?wx_fmt=jpeg
③确定提取图片链接的正则表达式
pattern = r'property="og:image" content="(.+?)"'
④编写运行爬虫程序
from re import findall
from urllib.request import urlopen
url = 'https://mp.weixin.qq.com/s/TH6Z5OlKNE50ljTHlrGjUg' #公众号推文地址
with urlopen(url) as fp:
content = fp.read().decode()
pattern = r'property="og:image" content="(.+?)"'
result = findall(pattern, content)
print(result)
for index, item in enumerate(result): #图片的序号和它在列表的链接
with urlopen(str(item)) as fp: #打开链接
with open(str(index) + '.jpeg', 'wb') as fp1: #将图片链接以二进制的方式写进fp1
fp1.write(fp.read())
3.requests库
http请求类型
方法 | 说明 |
---|---|
requests.request() | 构造一个请求 |
requests.get() | 获取html网页 |
requests.head() | 获取html网页头信息 |
requests.post() | 提交post请求 |
requests.put() | 提交put请求 |
requests.patch() | 提交局部修改请求 |
requests.delete() | 提交删除请求 |
requests.options() | 提交http请求 |
返回的是一个response对象,response对象包含爬虫返回的信息
response对象的信息
信息 | 说明 |
---|---|
.status_code | HTTP请求的返回状态(正常:200;异常:404) |
.text | HTTP响应内容的字符串形式 |
.content | HTTP响应内容的二进制形式 |
.headers | HTTP响应内容的头部信息 |
.encoding | (从头部信息)分析响应内容的编码形式 |
requests的请求接口有一个叫headers的参数,向它传递一个字典完成请求头的定制
headers是解决requests请求反爬的方法之一,相当于进去网页服务器本身,假装自己在爬取数据
headers中有很多内容,主要常用的就是user-agent 和 host,他们是以键对的形式展现出来,如果user-agent 以字典键对形式作为headers的内容,就可以反爬成功,就不需要其他键对;否则,需要加入headers下的更多键对形式。
获取网页headers的方法:右键->检查->网络->第一个文件最下面
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62'}
例:读取并下载图片文件
import requests
url = r'http://mmbiz.qpic.cn/mmbiz_jpg/1KichGsxpq6oxSGMG5H6V7v5W0Sz2ld2dtIlfqy4KdQV5yUKIhPOJQ3ztxyjb79Pxv29HbVibbmYhdyNiatpAia3AQ/0?wx_fmt=jpeg'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62'}
r = requests.get(url, headers=headers)
with open('picture.jpeg', 'wb') as fp: #把图片数据写入文件
fp.write(r.content)
4.BeautifulSoup
用request库下载了页面并转换成字符串后需要一个用来解析页面格式,提取有用信息的解析器
BeatuifulSoup是可调用若干的其他程式化的标签语言的解析器,然后来建立文档的层次结构
解析器 | 使用方法 |
---|---|
python标准库 | BeautifulSoup(markup, “html.parser”) |
lxml HTML解析器 | BeautifulSoup(markup, “lxml”) |
lxml XML解析器 | BeautifulSoup(markup, [“lxml-xml”]) BeautifulSoup(markup, “xml”) |
Html5lib | BeautifulSoup(markup, “Html5lib”) |
搜索方法:
方法 | 说明 |
---|---|
find_all(name, attrs, recursive,string, **kwargs) | 返回文档中符合条件的所有标记tag,是一个列表 |
find(name, attrs, recursive,string, **kwargs) | 返回文档中第一个符合条件的标记tag |
name:对标签名称的检索字符串
attrs:对标签属性值的检索字符串
recursive:是否对子节点全部检索,默认为True
string:<>…</>中检索字符串
**kwargs:关键词参数列表
用法:
from bs4 import BeautifulSoup
print(BeautifulSoup('Hello world!', 'lxml'))
#自动添加标签<html><body><p>Hello world!</p></body></html>
print(BeautifulSoup('<span>Hello world!', 'lxml'))
#自动补全标签<html><body><span>Hello world!</span></body></html>
from bs4 import BeautifulSoup
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
soup = BeautifulSoup(html_doc, 'html.parser')
print(soup.prettify())
#将内容以指定解释器优雅地表示出来
'''
<html>
<head>
<title>
The Dormouse's story
</title>
</head>
<body>
<p class="title">
<b>
The Dormouse's story
</b>
</p>
<p class="story">
Once upon a time there were three little sisters; and their names were
<a class="sister" href="http://example.com/elsie" id="link1">
Elsie
</a>
,
<a class="sister" href="http://example.com/lacie" id="link2">
Lacie
</a>
and
<a class="sister" href="http://example.com/tillie" id="link3">
Tillie
</a>
;
and they lived at the bottom of a well.
</p>
<p class="story">
...
</p>
</body>
</html>
'''
print(soup.get_text())
'''
返回所有文本:
The Dormouse's story
The Dormouse's story
Once upon a time there were three little sisters; and their names were
Elsie,
Lacie and
Tillie;
and they lived at the bottom of a well.
...
'''
print(soup.title) #查看<title>标签内容<title>The Dormouse's story</title>
print(soup.title.name) #查看标签名字title
print(soup.title.text) #查看标签文本The Dormouse's story
print(soup.title.string) #查看标签文本The Dormouse's story
print(soup.title.parent) #查看上一级标签<head><title>The Dormouse's story</title></head>
print(soup.body) #查看<body>标签内容
'''
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
</body>
'''
print(soup.body.p) #查看<body>标签中<p>标签的内容<p class="title"><b>The Dormouse's story</b></p>
print(soup.p) #查看<p>标签内容<p class="title"><b>The Dormouse's story</b></p>
print(soup.p['class']) #查看标签属性['title']
print(soup.p.get('class')) #查看标签属性['title']
print(soup.p.text) #查看段落文本The Dormouse's story
print(soup.p.contents) #查看段落内容[<b>The Dormouse's story</b>]
print(soup.a) #<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
print(soup.a.attrs) #查看标签所有属性{'href': 'http://example.com/elsie', 'class': ['sister'], 'id': 'link1'}
print(soup.find_all('a')) #找所有的<a>标签
'''
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
'''
print(soup.find_all(['a','b'])) #找所有的<a><b>标签
'''
[<b>The Dormouse's story</b>, <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
'''
print(soup.find(id = 'link3')) #找指定属性的标签<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
print(soup.find('a', id = 'link3')) #找指定属性的指定标签<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
test_doc = '<html><head></head><body><p></p><p></p></body></heml>'
s = BeautifulSoup(test_doc, 'lxml')
print(s.prettify())
'''
<html>
<head>
</head>
<body>
<p>
</p>
<p>
</p>
</body>
</html>
'''
for child in s.html.children:
print(child)
'''
遍历直接子标签
<head></head>
<body><p></p><p></p></body>
'''
for child in s.html.descendants:
print(child)
'''
遍历子孙标签
<head></head>
<body><p></p><p></p></body>
<p></p>
<p></p>
'''
5.scrapy爬虫
(1)scrapy爬虫框架
实现爬虫功能的一个软件结构和功能组件集合
scrapy爬虫框架的5个主要部分:
Engine | scrapy核心,相当于发动机,不用修改 |
Downloader | 下载器,根据用户需要下载页面 |
Scheduler | 调度器,对所有爬取请求进行调度管理 |
上述三个模块(均不允许修改):由Scheduler发送请求,经过Engine到达Downloader,Downloader Middlewares可以在三者之间进行用户可配置的控制 | |
Spiders | 爬虫,从网上提取信息,也可以提取url,让scrapy继续爬下一个页面 |
Item pipeline | 管道项目,处理爬取项 |
scrapy常用命令:
startproject | 创建一个新工程 |
genspider | 创建一个爬虫 |
setting | 获取爬虫配置信息 |
crawl | 运行一个爬虫 |
list | 列出工程所有的爬虫 |
shell | 启动URL调试命令 |
一个scrapy工程相当于一个单元,允许有多个爬虫,每个爬虫相当于一个spider模块
十四、十五、数据分析及可视化
pandas提供了大量的函数用于生成、访问、修改、保存不同类型的数据,处理缺失值、重复值、异常值,并能够结合另一个拓展库matplotlib进行数据可视化。
pandas提供了三种数据结构:(import pandas as pd)
①Series——带标签的一维数组
data = pd.Series(数据,索引)
②DataFrame——带标签且大小可变的二维数组
data = pd.Series(数据,索引,列名)
data.index 查看索引
data.columns 查看列名
data.values 查看值
data.describe() 平均值、标准差、最小值、最大值
data.sort_index(axis, ascending) 对索引操作axis = 0,对列操作axis = 1,降序ascending = False,升序ascending = True
data.sort_value(by) by = '列名'/by = ['列名1', '列名2'] 先按列名1升序排,相同再按列名2升序排
data.loc[行, 列] 选择与访问
data.iat[行, 列] 修改
分组:groupby
差分:diff
③Panel——带标签且大小可变的三维数组
可视化过程:
①调用DataFrame或Series生成数据df
②调用matplotlib中plot()方法绘图,即df.plot()
plot() 绘制折线图
scatter() 绘制散点图
pie() 绘制饼图
bar() 绘制柱状图
polar() 绘制雷达图
参考教材:《Python程序设计》董付国