目录

一、Python变量&数据类型&运算符

二、Python语言的控制流程

三、Python容器

四、Python字符串

五、Python函数

六、Python面向对象--类与对象/封装/继承/多态/模块/包/库

七、Python常见操作--文件操作/正则操作/日期操作/日志操作

【Python】开始学习叭(持续学习) - 吃怪兽的衰小孩 - 博客园学习视频:https://www.bilibili.com/video/BV1wD4y1o7AShttps://www.cnblogs.com/xuanling/p/14322302.html

一、Python变量&数据类型&运算符

1、print()函数

1.1 输出数字,字符串,含有运算符的表达式

print(123)
print('hello world')
print(3+1)

1.2 输出到控制台,输出到文件中(如果文件不存在,则新建文件)

# 输出到文件中需要使用file=输入到文件
fp = open('D:/text.txt', 'a+')  # a+ 表示如果文件不存在则创建,如果存在就在文件内容的后面继续追加
print('hello world', file=fp)
fp.close()# 不换行输出,输出在一行中
print('hello', 'world', 'python')

2、转义字符

2.1 当字符串中包含反斜杠,单引号,双引号是,需要用反斜杠来进行转义。比如:反斜杠:\\,单引号:\',双引号\"

2.2 当字符串中包含特殊意义的字符时。比如:换行:\n,回车:\r,水平制表符:\t,退格:\b

print('hello\tworld')
print('helloooo\tworld')  # \t制表符为4隔,若已经占用,则补全,未占用,则为4格
print('hello\rworld')  # 单行内回车,world会叭hello覆盖掉
print('hello\bworld')  # 向前退一格,w会占用o的位置print('http:\\\\www.baidu.com')
print('老师说:\'大家好\'')# 原字符:不希望字符串中的转义字符起作用,就是用原字符,就是在字符串之前加上r或R
print(r'hello\n world')  # 注意,最后一个字符不能是\
print(r'hello\n world\\')

3、标识符和保留字

3.1 标识符:变量、函数、类、模块和其他对象的起的名字

3.2 标识符规则:① 字母、数字、下划线组成 ② 不能用数字开头 ③ 不能使用保留字 ④ 严格区分大小写

3.3 保留字

import keyword
print(keyword.kwlist)>>>>['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

4、变量

4.1 变量是内存中一个带标签的盒子

4.2 变量组成

① 标识:表示对象所存储的内存地址,可以使用内置函数id()获取

② 类型:表示对象的数据类型,可以使用内置函数type()获取

③ 值:表示对象所存储的具体值,可以使用print()打印

name = '苹果'
print('标识:', id(name))
print('类型:', type(name))
print('值:', name)

4.3 变量的定义

① 变量名由大小写英文字母、数字和下划线_组成

② 变量不能用数字开头

③ 变量尽量不要和Python关键字重合(比如前面学习过的:and、or、not,否则可能导致Python原有关键字发挥不出作用)

注意:多次赋值后,变量名会指向新的空间(就近原则)。

5、数据数据类型

5.1 常见的数据类型

① 整数(int):可以表示正数,负数,0.可以表示为十进制,二进制(0b开头),八进制(0o开头),十六进制(0x开头)

② 浮点类型(float):由整数和小数部分组成,浮点数运算则可能会有四舍五入的误差

③ 布尔类型(bool):只有两个值,可以和整数转化,False(=0),True(=1)。可以用and、or和not运算

④ 字符串类型(str):不可变的字符序列。可以用单引号,双引号,三引号(可以在多行显示)定义

注意:

空值:是Python里一个特殊的值,用None表示。None和0是不一样的,None不能理解为0,因为0是有意义的,比如我有0个苹果表示我没有苹果,0表达的是数值0的意思,而不能表示为我有None个苹果,None是一个特殊的空值。

5.2 数据类型的转化

① 定义:将不同的数据类型的数据进行拼接

② int():转化成整数,文字类和小数类字符串,无法转化成整数;浮点数转化成整数:抹零取整

③ str():转化成字符串,也可以用引号转化

④ float():转化成浮点数,文字类无法转成整数;整数转成浮点数,末尾为.0

5.3 数据对象总结

str() # 字符串对象
int() # 整型对象
float() # 浮点型对象
list() # 列表对象
tuple() # 元组对象
dict() # 字典对象
set() # 字典对象
bool() # 布尔对象# 数字转字符串
print(str(1))  # ==> 1
# 字符串转数字
print(int(str(1)))  # ==> 1
# 集合转元组转列表
print(list(tuple(set({1, 2, 3}))))  # ==> [1, 2, 3]

6、注释

6.1 单行注释:只能注释一行。快捷键:Ctrl+ /。格式:# 注释内容

6.2 多行注释:注释多行内容用三引号格式(三个单引号或者三个双引号)。

6.3 中文编码声明注释:在文件开头加上中文声明注释,用以指定源码文件的编码格式 # coding:utf-8

7、input()函数

7.1 作用:接受来自用户的输入

7.2 返回值类型:输入值类型为str

7.3 值的存储:使用=对输入的值进行存储

# 从键盘录入两个整数,计算它们的和
a = input('请输入一个加数:')
b = input('请输入另一个加数:')
print(int(a) + int(b))>>>>
请输入一个加数:1
请输入另一个加数:2
3

8、运算符

8.1 算术运算符:加减乘除,幂运算,整除,取余

# 加法
num1 = 10
num2 = 0.5
result = num1 + num2
print(result)    # ==> 10.5
# 减法
result = num1 - num2
print(result)    # ==> 9.5
# 乘法
result = num1 * num2
print(result)    # ==> 5.0
# 除法
result = num1 / num2
print(result)   # ==>20.0
# 幂运算
print(2**3)     # ==>8
# 整除(地板除)
print(10//4)  # ==> 2
print(10//2.5)  # ==> 4.0
print(10//3)  # ==> 3
# 取余(取模运算)
print(3 % 2)    # ==> 1 因此3为奇数
print(33 % 2)   # ==> 1 因此33为奇数
print(100 % 2)  # ==> 0 因此100为偶数
# 小数点位数
num = 10 / 3
print(num)   # ==> 3.3333333333333335
print(round(num, 2))    # ==> 3.33

注意:round()函数:保留小数点后若干位。使用两个参数,第一个是需要保留小数点位数的数值,第二个是保留的位数。

8.2 赋值运算符

① 执行顺序从右到左

② 支持链式赋值:a = b = c = 20

③ 支持参数赋值:+=,-=,*=,/=,//=,%=

④ 支持系列解包赋值:a, b, c = 20, 30, 40

# 交换两个变量的值
a, b = 10, 20
print('交换前:', a, b)    # ==> 10 20
# 交换
a, b = b, a
print('交换后:', a, b)    # ==> 20 10

8.3 比较运算符

① 对变量或表达式的结果进行大小,真假等比较,结果是True或False

② >,<,>=,<=,!=

③ ==:对象value(值)的比较

④ is,is not:对象id(标识)的比较

a, b = 10, 20
print(a is b)       # ==> False
print(a is not b)   # ==> True

注意:一个 = 是赋值运算,两个 == 是比较运算

8.4 布尔运算符

① and(与运算):只有两个布尔值都为 True 时,计算结果才为 True

② or(或运算):只要有一个布尔值为 True,计算结果就是 True

③ nor(非运算):把True变为False,或者把False变为True

④ in,not in:in表示在某段内容中,not in 表示不再某段内容中

s = 'hello world'
print('w' in s)     # ==> True
print('w' not in s)     # ==> False
print('k' in s)     # ==> False

注意:Python把0、空字符串和None看成False,其他数值和非空字符串都看成True

短路计算:① 在计算a and b时,如果a是False,则根据与运算法则,整个结果必定为False,因此返回 a;如果a是True,则整个计算结果必定取决与b,因此返回b。② 在计算a or b时,如果a是True,则根据或运算法则,整个计算结果必定为True,因此返回 a;如果a是False,则整个计算结果必定取决于b,因此返回b。

8.5 位运算

① 位与(&):对应数位都是1,结果数位才是1,否则为0

② 位或(|):对应数位都是0,结果数位才是0,否则为1

③ 左移运算符(<<):高位溢出舍弃,低位补0

④ 右移运算符(>>):低位溢出舍弃,高位补0

print(4 & 8)    # ==> 0
print(4 | 8)    # ==> 12
print(4 >> 1)  # ==> 2 # 向右移动一位,相当于除2
print(4 << 1)  # ==> 8 # 向左移动一位,相当于乘2

8.6 运算符的优先级

算术运算符 > 位运算符 > 比较运算符 > 布尔运算符 > 赋值运算

二、Python语言的控制流程

1、程序的组织结构

1.1 顺序结构:从上到下顺序的执行代码,直到程序结束,没有任何判断和跳转

1.2 选择结构:根据判断条件的布尔值选择性的执行部分代码:if语句

1.3 循环结构:while语句和for-in语句

2、对象的布尔值

2.1 python中一切皆对象,所有对象都有布尔值,可以通过bool()来获取

2.2 以下对象布尔值均为False:False,数值0,None,空字符串,空列表,空元组,空字典,空集合

# 测试对象的布尔值,以下对象均为False,除此之外均为True
print(bool(False))
print(bool(0))
print(bool(0.0))
print(bool(None))
print(bool(''))  # 空字符串
print(bool(""))  # 空字符串
print(bool([]))  # 空列表
print(bool(list()))  # 空列表
print(bool(()))  # 空元组
print(bool(tuple()))  # 空元组
print(bool({}))  # 空字典
print(bool(dict()))  # 空字典
print(bool(set()))  # 空集合

3、选择结构

3.1 需要明确的让程序知道在什么条件下执行什么内容。

3.2 单分支结构

语法结构:

if 条件表达式:条件执行体

3.3 双分支结构

语法结构:

if 条件表达式:条件执行体1
else:条件执行体2
# 双分支结构:键盘输入一个整数,判断是奇数还是偶数
num = int(input('请输入一个整数:'))
if num % 2 == 0:print(num, '这是一个偶数!')
else:print(num, '这是一个奇数!!')

3.4 多分支结构

语法结构:

if 条件表达式1:条件执行体1
elif 条件表达式2:条件执行体2
elif 条件表达式3:条件执行体3
else:条件执行体其他
# 多分支结构:输入一个整数成绩,判断成绩的范围
score = int(input('请输入一个整数成绩:'))
if score>=90 and score<=100:print('A级')
elif score>=80 and score<=89:print('B级')
elif 70<=score<=79:  #python中可以按照数学格式来写,但是其他语言不行print('C级')
elif 60<=score<=69:print('D级')
elif score>=0 and score<=59:print('E级')
else:print('成绩输入不正确!!')

3.5 嵌套if

语法结构:

if 条件表达式1:if 内嵌条件表达式:内层条件执行体aelse:内层条件执行体b
else:条件执行体
# 嵌套if:输入一个金额,进行会员非会员的判断
answer = input('您是会员么?y/n')
money = float(input('输入您的购物金额:'))
if answer == 'y':if money >= 200:print('付款金额为:', money * 0.8)elif money >= 100:print('付款金额为:', money * 0.9)else:print('商品不打折', money)
else:  # 非会员if money >= 200:print('付款金额为:', money * 0.95)else:print('商品不打折', money)

3.6 条件表达式:if...else的简写

语法结构:

x if 判断条件 else y

如果判断条件为True,则返回x,如果判断条件是False,返回y

# 条件表达式:键盘输入两个整数,比较大小
num_a = int(input('请输入第一个整数:'))
num_b = int(input('请输入第二个整数:'))
print(num_a, '大于', num_b) if num_a >= num_b else print(num_a, '小于', num_b)      # ==> 3 小于 4
print(str(num_a)+'大于'+str(num_b) if num_a >= num_b else str(num_a)+'小于'+str(num_b))     # ==> 3小于4

3.7 pass语句

① 语句什么都不做,只是一个占位符,用在语法上需要的地方

② 什么时候用:先搭建语法结构,还没想好代码如何写的时候

③ 可以和什么语句一起用:if语句的条件执行体,for-in语句的循环体,定义函数时的函数体

# pass语句练习
answer = input('您是会员么?y/n')
if answer=='y':pass
else:pass

4、range()函数

4.1 用于生成一个整数序列

4.2 创建方式

① range(stop):创建一个(0,stop)之间的整数序列,步长为1

② range(start,stop):创建一个(start,stop)之间的整数序列,步长为1

③ range(start,stop,step):创建一个(start,stop)之间的整数序列,步长为step

# range()函数的创建方式
r = range(10)
print(r)  # ==>range(0, 10)
print(list(r))  # ==>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # 用于查看range对象中的整数序列,默认步长为1
r2 = range(1, 10)
print(list(r2))     # ==>[1, 2, 3, 4, 5, 6, 7, 8, 9]
r3 = range(1, 10, 2)
print(list(r3))     # ==>[1, 3, 5, 7, 9]

4.3 返回值:是一个迭代器对象(没有办法看到具体数据)

4.4 优点:不管range对象表示的整数序列有多长,所有range对象占用的内存空间都是相同的,因为仅仅需要存储start,stop和step,只有当用到range对象时,才回去审计序列中的相关元素

4.5 使用in与not in判断整数序列中是否存在/不存在指定的整数

# 判断指定元素是否存在range()中
r = range(10)
print(10 in r)      # ==>False
print(9 in r)        # ==>True
print(11 not in r)       # ==>True

5、循环结构

5.1 定义:反复做同一件事情

5.2 循环的分类:while循环,for-in循环

5.3 选择结构if和循环结构while的区别

① if是判断一次,条件为True执行一次

② while是判断N+1次,条件为True执行N次

5.4 while语法结构

while 条件表达式:条件执行体(循环体)

5.5 while循环:四步循环法

① 初始化变量

② 条件判断

③ 条件执行体(循环体)

④ 改变变量

总之:初始化的变量与条件判断的变量与改变的变量为同一个

# while循环计算0到4之间的累加和
a = 0
sum = 0
while a < 5:sum = sum + aa += 1
print('0到4之间的累加和为:', sum)# 计算1-100之间的偶数和
a = 1
sum = 0
while a <= 100:if not a % 2:  # 0 的布尔值为False,求偶数和需要求反    # if a % 2 == 0:  # 这是求偶数的和sum += aa += 1
print("计算1-100之间的偶数和", sum)

5.6 for-in循环

① in表示从(字符串,序列等)中依次取值,又称为遍历

② for-in遍历的对象必须是可迭代对象

③ 语法结构:

for 自定义的变量 in 可迭代对象:循环体

④ 循环体内不需要访问自定义变量,可以将自定义变量替换为下划线

# 遍历取出每个对象
for item in 'python':print(item)# range() 产生一个整数序列,也是可迭代对象
for i in range(10):print(i)# 如果不需要使用自定义变量,可将自定义变量些为 _
for _ in range(5):print('python学习')  # 这行文字会被输出5遍# 使用for循环计算1-100之间的偶数和
sum = 0
for item in range(1, 101):if item % 2 == 0:sum += item
print('1-100之间的偶数和为:', sum)# 输出100-999之间的水仙花数(比如:153 = 3*3*3 + 5*5*5 + 1*1*1)
for item in range(100, 1000):ge = item % 10  # 个位shi = item // 10 % 10  # 十位bai = item // 100  # 百位if ge**3 + shi**3 + bai**3 == item:print('这是一个水仙花', item)

6、流程控制语句break

6.1 用于结束循环结构(直接退出循环),通常与if一起使用

6.2 练习题

# 从键盘录入密码,最多3次,如果正确就结束循环
# 方式一:
for item in range(3):pwd = input('请输入密码:')if pwd == '888888':print('密码正确')breakelse:print('密码不正确!!')
# 方式二:
a = 0
while a < 3:pwd = input('请输入密码:')if pwd == '888888':print('密码正确')breakelse:print('密码不正确!!')a += 1

7、流程控制语句continue

7.1 用于结束当前循环,进入下一次循环,通常和if一起使用

7.2 练习题

# 要求输出1-50之间输出所有5的倍数
for item in range(1, 51):if item % 5 == 0:print(item)# 要求使用continue
for item in range(1, 51):if item % 5 != 0:continueprint(item)

8、else语句

8.1 使用场景

① if条件不成立的时候使用else

② while和for-in中没有碰到break时执行else

8.2 练习题

# 从键盘录入密码,最多3次,如果正确就结束循环
# 方式一:
for item in range(3):pwd = input('请输入密码:')if pwd == '888888':print('密码正确')breakelse:print('密码不正确!!')
else:print('3次机会用完')# 方式二:
a = 0
while a < 3:pwd = input('请输入密码:')if pwd == '888888':print('密码正确')breakelse:print('密码不正确!!')a += 1
else:print('3次机会用完')

9、嵌套循环

9.1 循环结构中又嵌套了另外的完整的循环结构,其中内层循环为外层循环的循环体来执行

9.2 练习题

# 输出三行四列的矩形
for i in range(1, 4):  # 表示行数,执行三次,一次是一行for j in range(1, 5):print('*', end='\t')  # 不换行输出print()  # 换行# 打印直角三角形
for i in range(1, 10):for j in range(i):print('*', end='')print()# 打印九九乘法表
for i in range(1, 10):for j in range(i):print(i, '*', j, '=', i*j, end='\t')print()

10、二重循环中的break和continue

10.1 二重循环中的break和continue用于控制本层循环

10.2 学习下面的循环输出的结果

# break
for i in range(5):for j in range(1, 11):if j % 2 == 0:breakprint(j)
# continue
for i in range(5):for j in range(1, 11):if j % 2 == 0:continueprint(j, end='\t')print()

三、Python容器

1、列表(list)

1.1 什么是列表

是一个‘大容器’,可以存储N多个元素简单来说就是其他语言中的数组。是一种有序的容器,放入list中的元素,将会按照一定顺序排列。和变量的区别,变量只可以存储一个对象的引用

1.2 创建

① 列表需要使用中括号[],元素之间使用英文的逗号进行分割

② 创建方式一:使用中括号

③ 创建方式二:使用内置函数list()

④ 创建方式三:列表生成式。简称为:生成列表的公式。注意:‘表达列表元素的表达式’中通常包含自定义变量

# 创建方式一
lis1 = ['hello', 'world', 98]
# 创建方式二
lst2 = list(['hello', 'world', 98])
# 创建方式三
lst = [i*i for i in range(1,10)]
print(lst)  # ==>[1, 4, 9, 16, 25, 36, 49, 64, 81]

1.3 特点

① 列表元素按顺序有序排列

② 索引映射唯一一个数据

③ 列表可以存储重复数据

④ 任意数据类型混存

⑤ 根据需要动态分配和回收内存

1.4 查询(获取列表中单个元素)

① 获取列表中制定元素的索引

# 获取索引
lis1 = ['hello', 'world', 98, 'hello', 8.6]
# 1、如查列表中存在N个相同元素,只返回相同元素中的第一个元素的索引
print(lis1.index('hello'))  # ==>0
# 2、如果查询的元素在列表中不存在,则会抛出ValueError
print(lis1.index('python'))  # ==>ValueError
# 3、还可以在指定的start和stop之间查找
print(lis1.index('hello', 1, 4))  # ==>3

② 获取列表中的单个元素

# 获取单个元素
lis1 = ['hello', 'world', 98, 'hello', 8.6]
# 1、正向索引从0到1
print(lis1[2])  # ==>98
# 2、逆向索引从-1开始
print(lis1[-2])  # ==>hello
# 3、指定索引不存在,抛出IndexError
print(lis1[10])  # ==>IndexError

③ 判断元素是否在列表中存在

lst = ['hello', 'world', 10, 'hello', 8.6]
print(10 in lst)  # ==>True
print(99 in lst)  # ==>False
print(100 not in lst)  # ==>True

④ 列表元素的遍历

# 遍历列表
lst = ['hello', 'world', 10, 'hello', 8.6]
for item in lst:print(item)

1.5 切片(获取列表中多个元素)

① 语法:列表名[start, stop, step]

② 切片的结果:原列表片段的拷贝

③ 切片的范围:[start, stop]

④ step默认为1:简写为[start, stop]

⑤ step为正数:从start开始往后计算切片

[:stop:step]切片的第一个元素默认是列表的第一个元素

[start::stop]切片的最后一个元素默认是列表的最后一个元素

⑥ step为负数:从start开始往前计算切片

[:stop:step]切片的第一个元素默认是列表的最后一个元素;

[start::stop]切片的最后一个元素默认是列表的第一个元素

# 切片练习
lis = [10, 20, 30, 40, 50, 60, 70, 80]
# start=1,stop=6,step=1
print(lis[1:6:1])  # ==>[20, 30, 40, 50, 60]
print(lis[1:6])    # 默认步长为1 (可写,可省略,也可不写)  ==>[20, 30, 40, 50, 60]
print(lis[1:6:])  # ==>[20, 30, 40, 50, 60]
# start=1,stop=6,step=2
print(lis[1:6:2])  # ==>[20, 40, 60]
# start为空,stop=6,step=2
print(lis[:6:2])  # start为空,则从0开始   ==>[10, 30, 50]
# start=1,stop为空,step=2
print(lis[1::2])  # stop为空,则从指定位置查到最后一个元素   ==>[20, 40, 60, 80]# step为负数
print('原列表:', lis)  # ==>原列表: [10, 20, 30, 40, 50, 60, 70, 80]
print(lis[::-1])  # 将原列表反过来了  # ==>[80, 70, 60, 50, 40, 30, 20, 10]
# start=7,stop省略,step=-1
print(lis[7::-1])  # ==>[80, 70, 60, 50, 40, 30, 20, 10]
# start=6,stop=0,step=-2
print(lis[6:0:-2])  # ==>[70, 50, 30]

1.6 增加操作

① append():在列表的末尾添加一个元素

② extend():在列表的末尾至少添加一个元素

③ insert():在列表的任意位置添加一个元素

④ 切片:在列表的任意位置添加至少一个元素

# 添加元素练习
lst = [10, 20, 30]
lst.append(100)
print(lst)  # ==>[10, 20, 30, 100]lst2 = ['hello', 'world']
lst.append(lst2)  # 将lst2作为一个元素添加到列表末尾
print(lst)  # ==>[10, 20, 30, 100, ['hello', 'world']]lst.extend(lst2)  # 将lst2中每个元素添加到列表末尾
print(lst)  # ==>[10, 20, 30, 100, ['hello', 'world'], 'hello', 'world']lst.insert(1, 'python')  # 添加到指定索引的位置
print(lst)  # ==>[10, 'python', 20, 30, 100, ['hello', 'world'], 'hello', 'world']lst3 = [True, False, 'hello']
lst[1:] = lst3  # 相当于把切片的内容全部切掉,然后添加新的元素
print(lst)  # ==>[10, True, False, 'hello']

1.7 删除操作

① remove():一次只能删除一个,重复元素只删除第一个,元素不存在则报ValueError

② pop():删除一个指定索引位置上的元素,指定索引不存在抛出IndexError,不指定索引时删除列表中最后一个元素

③ 切片:一次至少删除一个元素

④ clear():清空列表

⑤ del:删除列表

# 删除练习
lis = [10, 20, 30, 40, 50, 60, 30]
# 从列表中移除一个元素,如果有重复的移除第一个
lis.remove(30)
print(lis)  # ==>[10, 20, 40, 50, 60, 30]
# remove元素不存在报错
lis.remove(100)
print(lis)  # ==>ValueError# pop删除指定索引的值
lis.pop(1)
print(lis)  # ==>[10, 40, 50, 60, 30]
# pop删除索引不存在会报错
lis.pop(5)
print(lis)  # ==>IndexError
# pop不指定参数,删除最后一个
lis.pop()
print(lis)  # ==>[10, 40, 50, 60]# 切片:删除至少一个元素,但是会产生新的列表对象
new_lis = lis[1:3]
print('原列表:', lis)  # ==>原列表: [10, 40, 50, 60]
print('新列表:', new_lis)  # ==>新列表: [40, 50]
# 切片:不产生新的列表对象,而是删除原列表中的内容
lis[1:3] = []
print(lis)  # ==>[10, 60]# 清除列表
lis.clear()
print(lis)   # ==>[]# del是直接将列表对象删除,这个对象没有了,当前不能调用了
del lis
print(lis)   # ==>NameError

1.8 修改操作

① 为指定索引的元素赋予一个新值

② 为指定的切片赋予一个新值

# 修改练习
lst = [10, 20, 30, 40]
lst[2] = 100  # 一次修改一个值
print(lst)  # ==>[10, 20, 100, 40]lst[1:3] = [300, 400, 500, 600]  # 修改至少一个值
print(lst)  # ==>[10, 300, 400, 500, 600, 40]

1.9 排序操作

① sort():列表中所有元素按照从小到大的顺序排序,使用reverse=True,进行降序排列

② 内置函数sorted():可以指定reverse=True,进行降序排列,原列表不发生变化

# 排序操作
lis = [20, 40, 10, 98, 54]
# 调用sort方法,默认是升序,不产生新的列表
lis.sort()
print(lis)  # ==>[10, 20, 40, 54, 98]
lis.sort(reverse=True)
print(lis)  # ==>[98, 54, 40, 20, 10]
lis.sort(reverse=False)
print(lis)  # ==>[10, 20, 40, 54, 98]# 直接使用内置函数排序,默认为升序,会产生新的列表对象
lis2 = [20, 40, 10, 98, 54]
new_lis2 = sorted(lis2)
print('原列表:', lis2)  # ==>原列表: [20, 40, 10, 98, 54]
print('新列表:', new_lis2)  # ==>新列表: [10, 20, 40, 54, 98]
# 降序排列
new_lis3 = sorted(lis2, reverse=True)
print(new_lis3)  # ==>[98, 54, 40, 20, 10]

2、字典(dict)

2.1 什么是字典:python中内置的数据结构之一,与列表一样是一个可变序列。以键值对的方式存储数据,字典是一个无序的序列

2.2 创建

① 创建方式一:使用花括号

② 创建方式二:使用内置函数dict()

③ 创建方式三:使用内置函数zip()

# 使用{}来创建
score = {'张三': 100, '李四': 98, '王五': 45}
print(score)
print(type(score))# 使用dict()创建
student = dict(name='jack', age=20)
print(student)  # ==>{'name': 'jack', 'age': 20}# 创建一个空字典
d = {}
print(d)# 使用内置函数zip
items = ['fruits', 'books', 'other']
prices = [98, 78, 67, 100, 102]
d = {item: price for item, price in zip(items, prices)}
print(d)  # 使用zip函数时会以短的为基准,多余的忽略 ==>{'fruits': 98, 'books': 78, 'other': 67}# 使用{}来创建
score = {'张三': 100, '李四': 98, '王五': 45}
print(score)
print(type(score))

2.3 特点

① 字典中的所有元素都是一个key-value对,key不允许重复,vlaue可以重复

② 字典中的元素是无序的

③ 字典中的key必须是不可变对象

④ 字典也是可以根据需要动态的伸缩

⑤ 字典会浪费较大的内存,是一种使用空间换时间的数据结构

2.4 元素查询

① []

② get()方法

③ []和get()取值的区别:[]如果字典中不存在指定的key,抛出keyError异常;get()取值,如果字典中不存在指定key,不会拋异常而是返回None,可以通过参数设置默认的vlaue,可以在key不存在时返回

# 元素查询[]方式
score = {'张三': 100, '李四': 98, '王五': 45}
# 方式一:[]方式
print(score['张三'])
print(score['陈六'])  # key不存在时会报KeyError# 方式二:get方式
print(score.get('张三'))
print(score.get('陈六'))  # ==>None
print(score.get('拉拉', 99))  # ==>99是查找拉拉时如果不存在返回的默认值

2.5 常用操作

① key的判断:in / not in

② 元素的删除:del / clear()

③ 元素的新增:直接指定key对应的值

score = {'张三': 100, '李四': 98, '王五': 45}
# key的判断
print('张三' in score)  # ==>True
print('张三' not in score)  # ==>False# 删除元素
del score['张三']  # 删除指定的key-vlaue对
print(score)  # ==>{'李四': 98, '王五': 45}
score.clear()  # 清空字典中所有元素
print(score)  # ==>{}# 新增元素
score['哈哈'] = 50  # 新增时若key不存在则新增
print(score)  # ==>{'李四': 98, '王五': 45, '哈哈': 50}
# 修改元素
score['哈哈'] = 100  # 新增时若key存在则修改key对应的value值
print(score)  # ==>{'李四': 98, '王五': 45, '哈哈': 100}

2.6 获取字典视图

① keys():获取字典中所有key

② values():获取字典中所有vlaue值

③ items():获取字典中所有key,vlaue对

score = {'张三': 100, '李四': 98, '王五': 45}
# 获取所有的key
keys = score.keys()
print(keys)  # ==>dict_keys(['张三', '李四', '王五'])
print(type(keys))  # ==><class 'dict_keys'>
print(list(keys))  # 将key转化为list列表格式 ==>['张三', '李四', '王五']# 获取所有的value
values= score.values()
print(values)  # ==>dict_values([100, 98, 45])
print(type(values))  # ==><class 'dict_values'>
print(list(values))  # ==>[100, 98, 45]# 获取所有key-value
items = score.items()
print(items)  # ==>dict_items([('张三', 100), ('李四', 98), ('王五', 45)])
print(type(items))  # ==><class 'dict_items'>
print(list(items))  # ==>[('张三', 100), ('李四', 98), ('王五', 45)]

2.7 字典元素的遍历

score = {'张三': 100, '李四': 98, '王五': 45}
# 字典的遍历
for item in score:print(item)  # ==> 输出的是字典中的keyprint(score[item])  # ==> 输出的是字典中的valueprint(score.get(item))  # ==> 输出的是字典中的value

3、元组(tuple)

3.1 元组:不可变序列

3.2 创建

① 创建方式一:使用小括号

② 创建方式二:使用内置函数tuple()

③ 创建方式三:只包含一个元组的元素需要使用逗号和小括号

# 方式一
t = ('python', 'world', 98)
print(t)
print(type(t))
t2 = 'python', 'world', 98  # 小括号可以省略
print(t2)
print(type(t2))# 方式二
t1 = tuple(('python', 'world', 98))
print(t1)
print(type(t1))# 方式三:创建一个元素的元组
t3 = ('python',)  # 只有一个元素时必须加上逗号
print(t3)
print(type(t3))
# 空元组创建
t4 = ()
print(t4)
print(type(t4))
t5 = tuple()
print(t5)
print(type(t5))

3.3 为什么元组是不可变序列

① 在多任务环境下,同时操作对象时不需要加锁,因此在程序中尽量使用不可变序列

② 元组中存储的是对象的引用。

③ 如果元组中对象本身不可对象,则不能在引用其他对象

④ 如果元组中的对象是可变对象,则可变对象的引用不允许改变,但是数据可以改变

t = (10, [20, 30], 9)
print(t[0], type(t[0]))
print(t[1], type(t[1]))
print(t[2], type(t[2]))
# 修改t[1]:不允许修改元素type,可以改变列表中的数据
t[1].append(100)
print(t)  # ==>(10, [20, 30, 100], 9)

3.4 元组的遍历

① 使用索引:前提是知道有多少个元素,超出索引号则报错

② for-in循环

# 元组遍历
t = ('python', 'world', 98)
# 方式一:使用索引
print(t[0])
print(t[1])
print(t[2])
# 方式二:使用for-in
for item in t:print(item)

4、集合(set)

4.1 什么是集合

① 内置数据结构

② 属于可变类型的序列

③ 集合是没有vlaue的字典

4.2 创建

① 创建方式一:使用花括号

② 创建方式二:使用内置函数set()

③ 创建方式三:集合生成式

# 集合的创建
# 方式一
s = {1, 2, 3, 4, 5, 4, 3, 6, 7}
print(s)  # ==>{1, 2, 3, 4, 5, 6, 7}
# 方式二
s = set(range(6))
print(s)  # ==>{0, 1, 2, 3, 4, 5}
# 列表转化集合,同时去掉重复元素
print(set([3, 4, 55, 59, 3]))  # ==>{59, 3, 4, 55}
# 元组转化集合
print(set((4, 5, 6, 7)))  # ==>{4, 5, 6, 7}
# 字符串转化集合
print(set('python'))  # ==>{'h', 'n', 't', 'p', 'o', 'y'}
#  集合转化集合
print(set({9, 8, 7, 6}))  # ==>{8, 9, 6, 7}
# 空集合:直接使用{}不行,{}默认是空字典
print(set())  # ==> set()
# 利用生成式
s = {i for i in range(1, 10)}
print(s)  # ==>{1, 2, 3, 4, 5, 6, 7, 8, 9}

4.3 特点

① 集合中的元素不能重复,若重复会直接去重

② 集合的元素是无序的

③ 是一个可变序列

4.4 判断操作:in / not in

# 判断操作
s = {10, 20, 30, 40, 50}
print(10 in s)  # ==>True
print(100 not in s)  # ==>True
print(100 in s)  # ==>False

4.5 新增操作

① add():一次添加一个元素

② update():至少添加一个元素

# 新增
s = {10, 20, 30, 40, 50}
s.add(233)  # 一次添加一个元素
print(s)  # ==>{40, 233, 10, 50, 20, 30}
s.update({99, 88, 77})  # 一次至少添加一个元素
print(s)  # ==>{99, 40, 233, 10, 77, 50, 20, 88, 30}
# 这个过程只是叭里面对应的元素加到集合中,而不是叭列表这个对象添加到集合
s.update([100, 101, 102])
print(s)  # ==>{99, 100, 101, 102, 40, 233, 10, 77, 50, 20, 88, 30}
s.update((222, 333, 444))
print(s)  # ==>{99, 100, 101, 102, 40, 233, 10, 77, 333, 50, 20, 88, 444, 222, 30}

4.6 删除操作

① remove():一次删除一个元素,如果元素不存在则抛出KeyError

② discard():一次删除一个指定元素,如果元素不存在不抛出异常

③ pop():一次至删除一个元素,不能指定参数

④ clear():清空集合

# 删除练习
s = {10, 20, 30, 40, 50}
s.remove(10)
print(s)  # ==>{40, 50, 20, 30}
# s.remove(500)
print(s)  # 抛出异常:KeyErrors.discard(500)  # 不会抛出异常
print(s)  # ==> {40, 50, 20, 30}s.pop()  # 不能指定参数,使用后删除任意一个元素
print(s)s.clear()
print(s)  # ==>set()

4.7 集合间的关系

① 判断是否相等:== / !=

② 判断是否是子集:issubset()

③ 判断是否是超集:issuperset()

④ 判断是否没有交集:isdisjoint()

# 集合关系练习
s1 = {10, 20, 30, 40}
s2 = {30, 40, 20, 10}
# 判断集合是否相等:元素相同就相等
print(s1 == s2)  # ==>True
print(s1 != s2)  # ==>Falses1 = {10, 20, 30, 40, 50, 60}
s2 = {10, 20, 30, 40}
s3 = {10, 20, 90}
# 判断是否是子集
print(s2.issubset(s1))  # ==>True
print(s3.issubset(s1))  # ==>False
# 判断是否是超集
print(s1.issuperset(s2))  # ==>True
print(s1.issuperset(s3))  # ==>False
# 判断是否是没有有交集: 没有交集返回True,有交集返回False
print(s1.isdisjoint(s2))  # ==>False
print(s2.isdisjoint(s1))  # ==>False
print(s1.isdisjoint(s3))  # ==>False
print(s2.isdisjoint(s3))  # ==>False
s4 = {100, 200, 300}
print(s4.isdisjoint(s3))  # ==>True

4.8 集合间的数学计算

① 交集:intersection()

② 并集:union()会自己去重操作

③ 差集:difference()

④ 对称差集:symmetric_difference()

# 数学计算
# 交集
s1 = {10, 20, 30, 40}
s2 = {20, 30, 40, 50, 60}
print(s1.intersection(s2))  # ==>{40, 20, 30}
print(s1 & s2)  # ==>{40, 20, 30}
# 并集
print(s1.union(s2))  # ==>{40, 10, 50, 20, 60, 30}
print(s1 | s2)  # ==>{40, 10, 50, 20, 60, 30}
# 差集:先计算交集,在从当中去除交集元素
print(s1.difference(s2))  # ==>{10}
print(s1 - s2)  # ==>{10}
# 对称差集:先计算交集,然后两个集合同时去除交集后的数据的集合
print(s1.symmetric_difference(s2))  # ==>{50, 10, 60}
print(s1 ^ s2)  # ==>{50, 10, 60}

5、列表、字典、元组、集合总结

四、Python字符串

1、认识字符串

1.1 是基本数据类型,是一个不可变的字符序列

1.2 字符串的驻留机制:仅保存一份相同且不可变字符串的方法,不同的值被存放在字符串的驻留池中,后续创建相同的字符串时,不会开辟新空间,而是叭该字符串的地址赋给新创建的变量。

1.3 驻留机制的几种情况(交互模式)----了解一下

① 字符串的长度为0或者1时

② 符合标识符的字符串

③ 字符串只在编译时进行驻留,而非运行时

④ [-5,256]之间的i整数数字

# 打开交互模式
C:\Users\Administrator>python
Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
# 长度为0或者1时驻留
>>> s1=''
>>> s2=''
>>> si is s2
# 符合标识符的字符串驻留
>>> s1 = 'abc%'
>>> s2 = 'abc%'
>>> s1 is s2
False
>>> id(s1)
2373409098192
>>> id(s2)
2373409098248
>>>
>>> s1 = 'abcx'
>>> s2 = 'abcx'
>>> s1 is s2
True
>>> id(s1)
2373409098360
>>> id(s2)
2373409098360
>>>
# 直接运行的时候不驻留
>>> a='abc'
>>> b='ab'+'c'
>>> c=''.join(['ab'+'c'])
>>> a is b
True
>>> a is c
False
>>> a
'abc'
>>> type(a)
<class 'str'>
>>> c
'abc'
>>> type(c)
<class 'str'>
# 编译是驻留
>>> a is c
True

2、字符串的常用操作(*****)

2.1 查询

① index():查询子串substr第一次出现的位置,如果查找的子串不存在时,则抛出ValueError

② rindex():查询子串substr最后一次出现的位置,如果查找的子串不存在时,则抛出ValueError

③ find():查询子串substr第一次出现的位置,如果查找的子串不存在时,则返回-1

④ rfind():查询子串substr最后一次出现的位置,如果查找的子串不存在时,则返回-1

# 查询练习
s = 'hello,hello'
print(s.index('lo'))  # ==>3
print(s.find('lo'))  # ==>3
print(s.rindex('lo'))  # ==>9
print(s.rfind('lo'))  # ==>9print(s.index('k'))  # ==>ValueError
print(s.find('k'))  # ==>-1
print(s.rindex('k'))  # ==>ValueError
print(s.rfind('k'))  # ==>-1

2.2 大小写转换

① upper():叭字符串中所有字符都转成大写字母

② lower():叭字符串中所有字符都转成小写字母

③ swapcase():叭字符串中所有大写字母转成小写字母,小写字母转成大写字母

④ capitalize():叭第一个字符转换成大写,叭其余字符转换成小写

⑤ title():叭每个单词的第一个字符转换成大写,叭每个单词的剩余字符转换成小写

# 大小写转换练习,转换之后会产生新的字符串
s = 'hello,python'
a = s.upper()
print(a)  # ==>HELLO,PYTHON
print(s.lower())  # ==>hello,pythons1 = 'hELLo,Python'
print(s1.swapcase())  # ==>HellO,pYTHON
print(s1.capitalize())  # ==>Hello,python
print(s1.title())  # ==>Hello,Python

2.3 对齐操作

① center(width, fillchar):居中对齐,如果指定的长度小于原字符串的长度则返回原字符串。

width -- 字符串的总宽度

fillchar -- 可选参数,填充字符,默认为空格

② ljust(width, fillchar):左对齐,如果指定的长度小于原字符串的长度则返回原字符串。

width -- 指定字符串长度

fillchar -- 可选参数,填充字符,默认为空格

③ rjust(width, fillchar):右对齐,如果指定的长度小于字符串的长度则返回原字符串。

width -- 指定填充指定字符后中字符串的总长度

fillchar -- 可选参数,填充的字符,默认为空格

④ zfill(width):右对齐,前面填充0,如果指定的长度小于字符串的长度则返回原字符串。

width -- 指定字符串的长度。原字符串右对齐,前面填充0

# 对齐练习,空格不好区别,全用*练习
s = 'hello,Pythons'
# 居中
print(s.center(20, '*'))  # ==>***hello,Pythons****
# 左对齐
print(s.ljust(20, '*'))  # ==>hello,Pythons*******
print(s.ljust(10, '*'))  # ==>hello,Pythons
# 右对齐
print(s.rjust(20, '*'))  # ==>*******hello,Pythons
print(s.rjust(10, '*'))  # ==>hello,Pythons
# 右对齐,填充字符为0
print(s.zfill(20))  # ==>0000000hello,Pythons
print(s.zfill(10))  # ==>hello,Pythons
print('-1980'.zfill(8))  # ==>-0001980

2.4 分割操作

① split(sep, maxsplit):从字符串的左边开始分割,默认的分割符为空格,返回的值是一个列表

sep -- 指定的分隔符,默认空格

maxsplit -- 分割次数,经过最大次数分割之后,剩余的子串会单独作为一部分。

② rsplit(sep, maxsplit):从字符串的右边开始分割,默认的分割符为空格,返回的值是一个列表

sep -- 指定的分隔符,默认空格

maxsplit -- 分割次数,经过最大次数分割之后,剩余的子串会单独作为一部分。

# 默认分割是空格
s ='hello world python'
print(s.split())  # ==>['hello', 'world', 'python']s1 ='hello|world|python'
# 左边开始分割
print(s1.split())  # ==>['hello|world|python']
print(s1.split(sep='|'))  # ==>['hello', 'world', 'python']
print(s1.split(sep='|', maxsplit=1))   # ==>['hello', 'world|python']
# 右边开始分割
print(s1.rsplit())  # ==>['hello|world|python']
print(s1.rsplit(sep='|'))  # ==>['hello', 'world', 'python']
print(s1.rsplit(sep='|', maxsplit=1))   # ==>['hello|world', 'python']

2.5 判断字符串的操作

① isidentifier():判断指定的字符串是不是合法的标识符

② isspace():判断指定的字符串是否全部由空白字符组成(回车、换行、水平制表符、空格)

③ isalpha():判断指定的字符串是否全部由字母组成

④ isdecimal():判断指定字符串是否全部由十进制的数字组成

⑤ isnumeric():判断指定字符串是否全部由数字组成

⑥ isalnum():判断指定字符串是否全部由字母和数字组成

# 判断练习
s ='hello,python'
print(s.isidentifier())  # ==>False
print('hello'.isidentifier())  # ==>True
print('张三'.isidentifier())  # ==>True
print('张三_123'.isidentifier())  # ==>Trueprint('\t'.isspace())  # ==>True
print('\n'.isspace())  # ==>True
print('\r'.isspace())  # ==>True
print(' '.isspace())  # ==>True
print('\b'.isspace())  # ==>Falseprint('abc'.isalpha())  # ==>True
print('张三'.isalpha())  # ==>True
print('张三1'.isalpha())  # ==>Falseprint('123'.isdecimal())  # ==>True
print('123四'.isdecimal())  # ==>False
print('ⅠⅡⅢ'.isdecimal())  # ==>Falseprint('123'.isnumeric())  # ==>True
print('123四'.isnumeric())  # ==>True
print('ⅠⅡⅢ'.isnumeric())  # ==>Trueprint('abc1'.isalnum())  # ==>True
print('张三123'.isalnum())  # ==>True
print('abc!'.isalnum())  # ==>False

2.6 字符串替换

① replace(old, new, count):该方法返回替换后得到的字符串,替换前后的字符串不发生变化

old -- 指定被替换的子串

new -- 指定替换子串的字符串

count -- 指定最大替换次数

# 替换练习
s = 'hello,Python'
print(s.replace('Python', 'java'))  # ==>hello,java
s = 'hello,Python,Python,Python'
print(s.replace('Python', 'java', 2))  # ==>hello,java,java,Python

2.7 字符串合并

① join():将列表或元组中的字符串合并成一个字符串

lis = ['hello', 'java', 'python']
print('|'.join(lis))  # ==>hello|java|python
print('_'.join(lis))  # ==>hello_java_pythont = ('hello', 'java', 'python')
print('|'.join(t))  # ==>hello|java|python
print('_'.join(t))  # ==>hello_java_pythonprint('*'.join('python'))  # ==>p*y*t*h*o*n

2.8 字符串的切片

① 切片将产生新的对象

② 操作类似于列表的切片

s = 'hello,python'
# 没有起始位置,从0开始
s1 = s[:5]
print(s1)  # ==>hello
# 没有指定结束位置,直接切到结束
s2 = s[6:]
print(s2)  # ==>python
s3 = '!'
new_s = s1 + s2 + s3
print(new_s)  # ==>hellopython!
# 从1开始切到5(不包括5),步长为1
print(s[1:5:1])  # ==>ello
# 没哟开始和结束,默认从0开始到字符串的最后一个元素
print(s[::2])  # ==>hlopto
# 默认从字符串的最后一个元素开始,到字符串的第一个元素结束,因为步长为负数
print(s[::-1])  # ==>nohtyp,olleh
print(s[-6::1])  # ==>python

3、字符串比较操作

3.1 运算符:>、>=、<、<=、==、!=

3.2 比较规则:首先比较两个字符串中的第一个字符,如果相等则继续比较下一个字符,依次比较下去,直到两个字符串中的字符不相等时,其比较结果就是两个字符串的比较结果,两个字符串中的所有后续字符将不再被比较

3.3 比较原理:比较的其实是原始值,可以通过内置函数ord来获取指定字符的原始值,相对的是内置函数chr,可以通过chr获取指定原始值对应的字符。

# 比较操作
print('apple' > 'app')  # ==>True
print('apple' > 'banana')  # ==>False
print(ord('a'))  # ==>97
print(ord('b'))  # ==>98print(chr(97))  # ==>a# ==与is的区别:==比较的是vlaue是否相等,is比较的是id是否相同
a = b = 'python'
c = 'python'
print(a == b)  # ==>True
print(b == c)  # ==>True
print(a is b)  # ==>True
print(a is c)  # ==>True

4、格式化字符串

4.1 格式化字符串的方式

① 方式一:%作占位符(%s:字符串、%d:整数、%f:浮点数、%.nf:保留n位小数)

② 方式二:{}作占位符(format)

③ 方式三:f-string

# 方式一:%
name = '张三'
age = 20
print('我叫%s,今天%d岁' % (name, age))  # ==>我叫张三,今天20岁
# 方式二:{}
print('我叫{},今天{}岁'.format(name, age))  # ==>我叫张三,今天20岁
# 方式三:f-string
print(f'我叫{name},今天{age}岁')  # ==>我叫张三,今天20岁print('%d' % 99)  # ==>99
# 这里的10表示宽度
print('%10d' % 99)  # ==>        99
# 这里.3表示保留的位数
print('%f' % 3.1415926)  # ==>3.141593
print('%.3f' % 3.1415926)  # ==>3.142
# 这里10.3 表示宽度为10,精度为小数点后3位
print('%10.3f' % 3.1415926)  # ==>     3.142print('{}'.format(3.1415925))  # ==>3.1415925
# 这里.3 表示的是一共3位数,0 表示占位符的顺序,可以省略
print('{0:.3}'.format(3.1415925))  # ==>3.14
print('{:.3}'.format(3.1415925))  # ==>3.14
# .3f表示3位小数
print('{:.3f}'.format(3.1415925))  # ==>3.142
# 同时设置宽度和精度,一共10位,3位是小数
print('{:10.3f}'.format(3.1415925))  # ==>     3.142

4.2 raw字符串与多行字符串:一个字符串包含很多需要转义的字符,对每一个字符都进行转义会很麻烦。为了避免这种情况,我们可以在字符串前面加个前缀r,表示这是一个 raw 字符串,里面的字符就不需要转义了

print(r'\(~_~)/ \(~_~)/')  # ==>\(~_~)/ \(~_~)/
print(r'\n\t\r')  # ==>\n\t\r

5、字符串的编码

5.1 编码:将字符串转换为二进制数据(bytes)

5.2 解码:将bytes类型的数据转换为字符串类型

5.3 python3中,默认使用UTF-8 Unicode来进行编码

s = '好好学习'
# 编码
print(s.encode(encoding='GBK'))  # GBK编码中一个中文占两个字节
print(s.encode(encoding='UTF-8'))  # UTF-8编码中一个中文占三个字节
# 解码
byte = s.encode(encoding='GBK')
print(byte.decode(encoding='gbk'))
# 编码和解码的类型要一致
print(byte.decode(encoding='utf-8'))  # ==>UnicodeDecodeError

5.4 常见其他函数

len(string):返回字符串长度

isdigit():如果字符创只包含数字则返回True

strip():截掉字符串左边和末尾的空格或指定字符

lstrip():截掉字符串左边的空格或指定字符

rstrip():删除字符串字符串末尾的空格

casefold:将字符串中的所有大写字母转换为小写字母,方法返回一个字符串,其中所有字符均为小写。lower()方法只对ASCII编码,即‘A-Z’有效,对于其它语言中把大写转换为小写的情况无效,只能用 casefold() 函数

count():统计字符串里某个字符出现的次数。可以选择字符串索引的起始位置和结束位置

endswith():判断字符串是否以指定字符或子字符串结尾

startswith():判断字符串是否以指定字符或子字符串开头

islower():检测字符串中的字母是否全由小写字母组成,返回值为布尔类型(True,False)

isupper():检测字符串中的字母是否全由大写字母组成,返回值为布尔类型(True,False)

isprintable():判断字符串中是否有打印后不可见的内容,返回值为布尔类型(True,False)

istitle():检测判断字符串中所有单词的首字母是否为大写,且其它字母是否为小写,字符串中可以存在其它非字母的字符,返回值为布尔类型(True,False)

6、字符串练习

6.1 字符串去重复

str2 = "cdab12ab34cd56ab78ab"
# 方式一
def Remove_Same(str1):flag = 0  # 标记是否与加入的元素相重合temp = str1[0:2]for i in range(1, int(len(str1))):for j in range(0, i):if str1[2 * j:2 * j + 2] == str1[2 * i:2 * i + 2]:flag = 1  # 若之前有元素想同则标记1breakif flag == 0:  # 无重复元素则加入temp = temp + str1[2 * i:2 * i + 2]else:  # 重复元素,flag置0进入下一个循环flag = 0return temp
print(Remove_Same(str2))    # ==> cdab12345678# 方式二
str1 = "ab12ab34abs56absc78aaaaa90"
new_str = ''
for i in str1:if i not in new_str:new_str += i
print(new_str)  # ==> cdab12345678# 场景三
str1 = "12323adfa12sad121adc"
def Remove_Same(str1):flag = 0  # 标记是否与加入的元素相重合temp = str1[0:1]for i in range(1, int(len(str1))):for j in range(0, i):if str1[j] == str1[i]:flag = 1breakif flag == 0:  # 无重复元素则加入temp = temp + str1[i]else:  # 重复元素,flag置0进入下一个循环flag = 0return tempprint(Remove_Same(str1))    # ==> 123adfsc

6.2 字符串数组互转

str = '1,2,3'
arr = str.split(',')
print(arr)  # ==> ['1', '2', '3']arr = ['a', 'b']
str = ','.join(arr)
print(str)  # ==> a,b

6.3 删除、截取,删除某个字符、片段

# 使用字符串切片
str1 = '1abcd.txt'
str2 = str1[1:-4]
print(str2)  # ==> abcd# 删除
str1 = 'abkcd'
str2 = str1.replace('k', '')
print(str2)  # ==> abcd# 替换
str1 = 'abkcd'
str2 = str1.replace('k', '2')
print(str2)  # ==> ab2cd
6.4 字符串与数值比较
str1 = '0123456789'
str2 = str1.encode('utf-8')if str1[0] == 0x30:print('str1 get 0 ascii code')if str2[0] == 0x30:print('str2 get 0 ascii code')

6.4 字符串与数值比较

# 转换为整型格式的日期
days = '2021-07-28'
fmt_list = days.split('-')
new_fmt = ''.join(fmt_list)
print(new_fmt)  # ==> 20210728# 使用datetime进行转换
import datetimetext = '2021-7-10'
print(datetime.datetime.strptime(text, '%Y-%m-%d'))  # ==> 2021-07-10 00:00:00# 直接将数字作为参数
import datetimeprint(datetime.datetime(2021, 7, 1, 10, 10, 26))  # ==> 2021-07-01 10:10:26# 经过解析后的数字作为参数
days = '2021-07-28'
fmt_list = days.split('-')
y = int(fmt_list[0])
m = int(fmt_list[1])
d = int(fmt_list[2])
print(datetime.datetime(y, m, d))  # ==> 2021-07-28 00:00:00

五、Python函数

1、函数创建&调用

1.1 什么是函数

函数就是执行特定任务以完成特定功能的一段代码

1.2 函数的创建

def 函数名([输入参数]):函数体[return xxx]

1.3 函数的用途

① 复用代码

② 隐藏实现细节

③ 提高可维护性

④ 提高可读性便于调试

1.4 函数的调用

函数名([实际参数])

1.5 执行过程了解

2、函数的参数传递

2.1 位置实参:根据形参对应的位置进行实参传递

2.2 关键字实参:根据形参名称进行实参传递

2.3 一个例子

def calc(a, b):  # a,b称为形式参数,简称行参,形参的位置是在函数的定义处c = a + breturn c# 位置实参
result = calc(10, 20)  # 10,20称为实际参数的值,简称实参,实参的位置是函数的调用处
print(result)# 关键字实参
res = calc(b=10, a=20)  # 左侧的变量名称成为:关键字参数,实参名称可以和形参名称可以不一样
print(res)

2.4 在函数的调用过程中进行参数的传递

① 如果是不可变对象,在函数体的修改不会影响实参的值

② 如果是可变对象,在函数体的修改会影响到实参的值

def fun(arg1, arg2):print('arg1:', arg1)print('arg2:', arg2)arg1 = 100arg2.append(10)print('arg1----', arg1)print('arg2----', arg2)n1 = 11
n2 = [22, 33, 44]
fun(n1, n2)>>>>
arg1: 11
arg2: [22, 33, 44]
arg1---- 100
arg2---- [22, 33, 44, 10]

3、函数的返回值

3.1 函数返回多个值时,结果为元组

def fun(num):odd = []  # 存奇数even = []  # 存偶数for i in num:if i % 2:odd.append(i)else:even.append(i)return odd, evenlis = [10, 29, 34, 23, 53, 33, 44]
print(fun(lis))>>>>
([29, 23, 53, 33], [10, 34, 44])

3.2 如果函数没有返回值,函数执行完毕之后,不需要给调用体提供数据,return可以省略不写

3.3 如果函数的返回值是1个,直接返回类型

4、函数的参数定义

4.1 定义默认值参数

函数定义时,给行参设置默认值,只有与默认值不符的时候才需要传递实参

4.2 个数可变的位置参数

① 定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数

② 使用*定义个数可变的位置形参

③ 结果为一个元组

def fun(*args):  # 函数定义时可变的位置参数print(args)fun(10)
fun(10, 20)
fun(11, 22, 33)>>>>
(10,)
(10, 20)
(11, 22, 33)

4.3 个数可变的关键字形参

① 定义函数时,可能无法事先确定传递的关键字实参的个数时,使用可变的关键字形参

② 使用**定义个数可变的关键字形参

③ 结果为一个字典

def fun(**args):  print(args)fun(a=10)
fun(a=20, b=40)>>>>
{'a': 10}
{'a': 20, 'b': 40}

4.4 注意点

① 个数可变的位置参数,只能是1个

② 个数可变的关键字参数,只能是1个

③ 在一个函数的定义过程中,既有个数可变的关键字形参,也有个数可变的位置形参时,位置形参必须放在关键字形参之前

def fun1(*args1, **arg2):pass

4.5 函数定义时的形参的顺序问题

def fun1(a, b, *, c, d, **kwargs):passdef fun2(*args, **kwargs):passdef fun3(a, b=10, *args, **kwargs):pass

4.6 总结

5、变量的作用域

5.1 程序代码能访问该变量的区域

5.2 根据变量的有效范围分为2类

① 局部变量:在函数体内定义并使用的变量,只在函数内部有效,局部变量使用global声明后,这个变量就会变成全局变量

② 全局变量:函数体外定义的变量,可以作用于函数内外

def fun(a, b):c = a+b  # c称为局部变量(因为时在函数内部进行定义的变量),a,b为函数的形参,作用范围也是函数内部,相当于局部变量print(c)print(c)  # 报错,因为c超出了作用范围(超出了作用域,它只作用于函数内部)name = 'laoshi'  #函数外定义的变量,可作用于函数内外
print(name)
def fun2():print(name)# 调用fun2
fun2()def fun3():global age  # 函数内部定义的变量,是局部变量,当使用global声明,这个变量实际变成了全局变量age = 20print(age)fun3()
print(age)

6、递归函数

6.1 什么是递归函数

如果在一个函数的函数体内调用了该函数本身,这个函数就称为递归函数

6.2 递归的组成部分:递归调用与递归终止条件

6.3 递归的调用过程

① 每递归调用一次函数,都会在栈内存分配一个栈帧

② 每执行完一次函数,都会释放相应的空间

6.4 递归的优缺点

① 缺点:占用内存多,效率低

② 优点:思路和代码简单

6.5 使用递归计算阶乘

def fac(n):if n == 1:return 1else:return n*fac(n-1)print(fac(6))

6.6 斐波那契数列

def fib(n):if n == 1:return 1elif n == 2:return 1else:return fib(n-1)+fib(n-2)# 输出第6位的数字
print(fib(6))
# 输出数列前6位的数字
for i in range(1, 7):print(fib(i), end='\t')

7、匿名函数

7.1 所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数

① lambda 只是一个表达式,函数体比 def 简单很多

② lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去

③ lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数

④ 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率

7.2 语法

lambda [arg1 [,arg2,.....argn]]:expression

7.3 一个例子

sum = lambda arg1, arg2: arg1 + arg2print ("相加后的值为 : ", sum( 10, 20 ))
print ("相加后的值为 : ", sum( 20, 20 ))

8、异常

8.1 bug的产生

① 粗心导致的语法错误:SyntaxError

② 知识点不熟悉导致的错误

③ 思路不清晰,巧妙使用print()函数和#注释

④ 被动掉坑:try-except

8.2 不同异常类型的处理方式

① try-except处理:只能处理一个异常,如果出现不是except处的异常,程序会报错

# 两个数相除
try:a = input('输入第一个整数:')b = input('输入第二个整数:')res = a / bprint('结果是:', res)
except ZeroDivisionError:print('除数不能为0 !')
print('程序结束')

② 多except结构:捕获异常的顺序按照先子类后父类的顺序,为了避免可能出现的异常,可以在最后增加BaseException

# 两个数相除
try:a = input('输入第一个整数:')b = input('输入第二个整数:')res = a / bprint('结果是:', res)
except ZeroDivisionError:print('除数不能为0 !')
except ValueError:print('输入的不是数字,无法转化')
except BaseException:print('还是错误啊~~~~')
print('程序结束')

③ try-except-else:如果try中没有抛出异常,则执行else模块,如果try中抛出异常,则执行except模块

try:a = int(input('输入第一个整数:'))b = int(input('输入第二个整数:'))res = a / b
except BaseException as e:print('错误了!')
else:print('结果是:', res)

④ try-except-else-finally:finally模块无论是否发生异常都会被执行,能常用来释放try模块中申请的资源

# 两个数相除
try:a = int(input('输入第一个整数:'))b = int(input('输入第二个整数:'))res = a / b
except BaseException as e:print('错误了!')
else:print('结果是:', res)
finally:print('无论发生什么都要执行的内容')
print('程序结束了')

8.3 异常处理机制:traceback模块:打印异常信息

import traceback
try:print(10 / 0)
except:traceback.print_exc()

8.4 常见的异常类型

六、Python面向对象--类与对象/封装/继承/多态/模块/包/库

1、什么是面向对象编程

1.1 程序设计的范式:程序可控,易于理解

1.2 抽象并建立对象模型

1.3 程序是不同对象相互调用的逻辑。每个对象在代码中抽象出来其实就是类;描述类特征的成为属性;具体到某个类(独立的类)则称为实例

2、类与对象

2.1 类

① 类是多个类似事物的统称。能够帮助我们快速理解和判断事物的性质。(eg)一个模板,(人类)---是一个抽象的,没有实体的。

② 类的主体由一系列的属性和方法组成

③ 数据类型:不同的数据类型属于不同的类,使用内置函数type()可以查看数据类型

2.2 对象&属性&方法

① 对象:(eg)张三,李四,这个个例专业术语称为实例或对象,python中一切皆对象

② 属性:表示这类东西的特征。(eg)眼睛,嘴巴,鼻子

③ 方法:表示这类物体可以做的事情。(eg)吃饭,睡觉,学习

2.3 类和对象区别

① 类是对客观世界中事物得抽象

② 对象是类实例化后的实体

2.4 类的创建

① 语法:通过class关键字定义一个类;类名以大写字母开头

② 类的组成:类属性、实例方法、静态方法、类方法

2.5 对象的创建

① 对象的创建又称为类的实例化。当一个对象被创建后,包含3个方面的特性:对象的句柄(用于区分不同的对象)、属性和方法。

② 语法:实例名 = 类名()

③ 意义:有了实例,就可以调用类中的内容

2.6 类属性、类方法、静态方法

① 类属性:类中方法外的变量称为类属性,被该类的所有对象所共享。一般分为公有属性和私有属性,如果属性的名字以两个下划线开始,就表示为私有属性,没有下划线开始的表示公有属性。

② 类方法:用@classmethod修饰的方法,使用类名直接访问的方法。也分为公有方法和私有方法,私有方法不能被模块外的类或者方法调用,也不能被外部的类或函数调用。python利用staticmethon或@staticmethon 修饰器把普通的函数转换为静态方法

③ 静态方法:用@staticmethod修饰的方法,使用类名直接访问的方法

④ python的属性分为实例属性和静态属性,实例属性是以self为前缀的属性,如果构造函数中定义的属性没有使用self作为前缀声明,则该变量只是普通的局部变量,类中其它方法定义的变量也只是局部变量,而非类的实例属性

⑤ 内部类的使用:在类的内部定义类。内部类中的方法可以使用两种方法调用。

# 第一种:直接使用外部类调用内部类,生成内部类的实例,在调用内部类的方法
object_name = outclass_name.inclass_name()
object_name.method()# 第二种:先对外部类进行实例化,然后再实例化内部类,最后调用内部类的方法
out_name = outclass_name()
in_name = out_name.inclass_name()
in_name.method()

⑥ 一个例子

class Student:  # Student 为类的名称(类名)由一个或多个单词组成,每个单词的首字母大写,其余小写native_pace = '吉林'  # 直接写在类里的变量,称为类属性# 初始化方法def __init__(self, name, age):self.name = name  # self.name 称为实例属性,进行了一个赋值操作,将局部变量的name的值赋给实例属性self.age = age# 实例方法def eat(self):  # 采用类名.方法名(类的对象)调用时,需要传入selfprint('学生吃东西~~~~')# 静态方法:用@staticmethod修饰@staticmethoddef method():  # 静态方法中不允许写selfprint('这是静态方法')# 类方法:用@classmethod修饰@classmethoddef cm(cls):  # 类方法中写cls,采用类名.方法名(类的对象)调用的时候不需要传入clsprint('这是类方法')# 在类之内定义的称为方法,在类之外定义的称为函数
def drink():  # 定义在类之外,叫做函数print('喝水')print(Student)  # ==><class '__main__.Student'>
print(type(Student))  # ==><class 'type'>
print(id(Student))  # ==>1669260589880# 创建Student类的对象:根据类对象创建出来的对象,叫做实例对象
stu1 = Student('张三', 20)
print(stu1)
print(type(stu1))
print(id(stu1))# 对象调用类方法一,可以直接采用 对象名.方法名()
stu1.eat()  # ==>学生吃东西~~~~
print(stu1.name)  # ==>张三
print(stu1.age)  # ==>20# 对象调用类方法二
Student.eat(stu1)  # 类名.方法名(类的对象)-->实际上就是方法定义出的self# 类属性的使用方式
print(Student.native_pace)
stu2 = Student('李四', 33)
print(stu1.native_pace)
print(stu2.native_pace)
Student.native_pace = '天津'  # 修改类属性后,访问时所有值都改变
print(stu1.native_pace)
print(stu2.native_pace)# 类方法的使用方式
Student.cm()# 静态方法的使用方式
Student.method()    

2.7 动态绑定属性和方法

① python是动态语言,在创建对象之后,可以动态地绑定属性和方法

② 一个例子

class Student:def __init__(self, name, age):self.name = nameself.age = agedef eat(self):print(self.name + '在吃饭')# 一个Student类可以创建多个Student的实例对象,每个实例对象可以相同也可以不同
stu1 = Student('张三', 20)
stu2 = Student('李四', 33)# 为stu2动态绑定性别属性,但是stu1不存在性别属性
stu2.gender = '女'
print(stu1.name, stu1.age)
print(stu2.name, stu2.age, stu2.gender)# 为stu1单独绑定一个动态函数
def show():print('定义在类之外的,称函数')stu1.show = show  # 动态绑定方法
stu1.show()
stu2.show()  # stu2没有绑定这个方法,所以执行报错

2.8 常见的几个对类或对象属性的操作

① 判断属性是否存在

dir():获取对象或者类的所有属性、方法

hasattr():判断一个对象或类是否有指定的属性或方法

# dir() 获取一个对象或者类的所有属性、方法
class Human():def __init__(self, name, age):self.__name = nameself.__age = agedef say(self):print("Hello!")@staticmethoddef running():print("I am running.")h = Human("myname", 22)
print(dir(h))
# ==>['_Human__age', '_Human__name', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'running', 'say']# hasattr() 判断一个对象或类是否有指定的属性或方法
class ClassA():def __init__(self, name, age):self.__name = nameself.__age = agea = ClassA("my_name", 18)
print(hasattr(a, "name"))  # ==>False
print(hasattr(a, "__init__"))  # ==>True # hasattr函数也能判断没有制定的方法print(dir(a))
# ==>['_ClassA__age', '_ClassA__name', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

② 判断一个对象或者变量的类型

isinstance():判断a是不是指定类型

type():显示类型

# isinstance() 判断参数1是不是参数2类型
class Students():passa = Students()
b = list()print(isinstance(a, Students))  # ==>True
print(isinstance(b, list))  # ==>True
print(type(a))  # ==><class '__main__.Students'>

③ 获取类或对象的属性:getattr()

# getattr():获取制定的属性值
class ClassB():name = "my_name"age = 18def high(self):print("180cm")b = ClassB()
print(getattr(b, "age"))  # ==> 18
print(getattr(b, "high1", "404"))  # ==>404

④ 设置属性内容:setattr()

class ClassC():pass# setattr():设置属性的内容
c = ClassC()
setattr(c, "name", "hity")
print(c.name)  # ==>hity

⑤ 魔法函数:在特定时刻自动触发的函数,特点是函数名两侧有两个下划线,例如__init__函数

# 给类绑定方法
class A():passdef say(self):print("hi,{0}".format(self))A.say = say
A.say("yoyoyoyoyo")  # ==>hi,yoyoyoyoyo# 给对象绑定方法:给对象1绑定的方法,对象2是不起作用的
class A():passdef a(self, name):self.name = nameprint(self.name)a1 = A()  # 实例化
from types import MethodType  # 给对象a1绑定一个方法a1.a = MethodType(a, a1)
a1.a("key")  # ==>key# __slots__变量限制绑定属性:对绑定的属性进行限制,在定义类时定义__slots__变量
class ClassS():__slots__ = ("name", "age")s = ClassS()
s.name = "hino"
s.age = 19
s.score = 100  # 不能绑定,因为__slots__中没有score

2.9 总结

① 类对象:将具有相似属性和方法的对象总结抽象为类对象,可以定义相似的一些属性和方法,不同的实例对象去引用类对象的属性和方法,能减少代码的重复率。

② 类属性:类对象所有的属性,类对象和实例对象均可以访问,被它们共同拥有

③ 公有类属性:可以在类外修改类属性,需要通过类对象引用直接修改。类内可以通过类方法修改类属性。如果通过实例对象来引用类属性,相当于实例对象在实例方法中创建了一个和类属性相同的名字,等同于局部变量实例属性,和类属性无关。

④ 私有类属性:类外通过类对象引用不能直接更改,只能通过实例方法调用类对象更改。

⑤ 类方法:需要修饰器@classmethod,标示其为类方法,类方法的第一个参数必须为类对象,一般用cls表示,通过cls引用的必须是类属性和类方法。

⑥ 静态方法:需要修饰器@staticmethod,标示其为静态方法。需要做一些功能,和类相关,但不需要类和对象参与,此时可以使用静态方法,静态方法可以不需要参数。

⑦ 实例对象:通过类对象创建的实例对象

⑧ 实例属性:通过方法定义的属性

⑨ 私有实例属性:__开头定义的变量名;只能通过方法调用来更改

⑩ 公有实例属性:可以通过实例对象重新定义。

⑪ 实例方法:第一个参数公认为self,可以调用类对象和实例对象。

⑫ 私有方法:只能在类内调用,如果类外调用,则需要类内的公有方法调用类内的私有方法,在类外调用这个公有方法,则间接调用了私有方法。一个程序中最核心的内容,不能随意调用,可以设置为私有方法,通过公有方法的判断去调用私有方法!

⑬ 公有方法:可以在类内类外随意调用。

⑭ 魔法方法:例如__init__方法,用两个__前后包裹的方法

class Animal(object):  # 类对象age = 0  # 公有类属性
__like = None  # 私有类属性def __init__(self):  # 魔法方法
self.name = 'haha'  # 公有实例属性
self.__sex = 'man'  # 私有实例属性def smile(self):  # 公有方法  self指向实例对象
passdef __jump(self):  # 私有方法
pass@classmethod
def run(cls):  # 类方法  cls 指向类对象
pass@staticmethod
def msg():  # 静态方法,可以没有参数
pass

3、面向对象三大特征

3.1 封装:提高程序的安全性

① 将数据(属性)和行为(方法)包装到类对象中,在方法内部对属性进行操作,在类对象的外部调用方法。这样,无需关心方法内部的具体实现细节,从而隔离了复杂度

② 在python中没有专门的修饰符用于属性的私有,如果该属性不希望在类对象外部被访问,前面使用两个‘_’.

③ 一个例子

class Student:def __init__(self, name, age):self.name = nameself.__age = age  # 年龄不希望在类的外部被使用,所以加了两个__def show(self):print(self.name, self.__age)stu = Student('张三', 20)
stu.show()
# 在类的外部使用name和age
print(stu.name)
print(stu.__age)  # 出现报错,不能直接使用。AttributeError: 'Student' object has no attribute '__age'
print(dir(stu))  # 查看stu可以使用的全部属性和方法
print(stu._Student__age)  # 在类的外部访问

3.2 继承:提高代码的复用性

① 语法

class 子类类名(父类1, 父类2, ...):pass

② 如果一个类没有继承任何类,则默认继承object

③ python支持多继承

④ 定义子类时,必须在其构造函数中调用父类的构造函数:新类不需要重头编写,子类只需要实现缺少的新功能,继承父类所有的属性、功能

class Person(object):  # Person 继承object类def __init__(self, name, age):self.name = nameself.age = agedef info(self):print(self.name, self.age)class Student(Person):def __init__(self, name, age, stu_no):super().__init__(name, age)self.stu_no = stu_noclass Teacher(Person):def __init__(self, name, age, teach_year):super().__init__(name, age)self.teach_year = teach_yearstu = Student('张三', 20, '1001')
tea = Teacher('老师', 33, 10)stu.info()
tea.info()

⑤ 函数isinstance()可以判断一个变量的类型class Person(object)

class Person(object):def __init__(self, name, gender):self.name = nameself.gender = genderclass Student(Person):def __init__(self, name, gender, score):super(Student, self).__init__(name, gender)self.score = scoreclass Teacher(Person):def __init__(self, name, gender, course):super(Teacher, self).__init__(name, gender)self.course = coursep = Person('Tim', 'Male')
s = Student('Bob', 'Male', 88)
t = Teacher('Alice', 'Female', 'English')
# 在继承链上,一个父类的实例不能是子类类型,因为子类比父类多了一些属性和方法
print(isinstance(p, Person))  # ==>True   # p是Person类型
isinstance(p, Student)  # ==>False   # p不是Student类型
isinstance(p, Teacher)  # ==>False  # p不是Teacher类型# 在一条继承链上,一个实例可以看成它本身的类型,也可以看成它父类的类型
isinstance(s, Person)  # ==>True # s是Person类型
isinstance(s, Student)  # ==>True # s是Student类型
isinstance(s, Teacher)  # ==>False # s不是Teacher类型# isinstance也可以用于Python自有数据类型的判断
s = 'this is a string.'
n = 10
isinstance(s, int)  # ==> False
isinstance(n, str)  # ==> False

3.3 多态:提高程序的可扩展性和可维护性

① 多态就是“具有多种形态”,即使不知道一个变量所引用的对象到底时什么类型,仍然可以通过这个变量调用方法,在运行过程中根据变量所引用对象的类型,动态决定调用哪个对象中的方法

class Animal(object):def eat(self):print('动物要吃东西')class Dog(Animal):def eat(self):print('狗吃肉')class Cat(Animal):def eat(self):print('猫吃鱼')class Person(object):def eat(self):print('人。。吃五谷杂粮')def fun(animal):animal.eat()fun(Dog())
fun(Cat())
fun(Person())

② 动态语言(Python)也可以叫做‘鸭子类型’:当一只鸟看起来像鸭子,走起来像鸭子,那么这只鸟就是鸭子。在鸭子类型中,不需要关心对象是什么类型,只关心对象的行为。

③ 静态语言(Java)实现多态的三个条件:1>继承 2>方法重写 3>父类引用指向子类对象

4、方法重写

4.1 如果子类对继承自父类的某个属性或者方法不满意,可以在子类中对其(方法体)进行重新编写

4.2 子类重写后的方法中可以通过super().xxx()调用父类中被重写的方法

4.3 一个例子

class Person(object):  # Person 继承object类def __init__(self, name, age):self.name = nameself.age = agedef info(self):print(self.name, self.age)class Student(Person):def __init__(self, name, age, stu_no):super().__init__(name, age)self.stu_no = stu_no# 重写父类中的info方法def info(self):super().info()  # 会先执行父类中的info方法print(self.stu_no)class Teacher(Person):def __init__(self, name, age, teach_year):super().__init__(name, age)self.teach_year = teach_year# 重写父类中的info方法def info(self):super().info()  # 会先执行父类中的info方法print(self.teach_year)stu = Student('张三', 20, '1001')
tea = Teacher('老师', 33, 10)stu.info()
tea.info()

5、object类

5.1 object类时所有类的父类,因此所有类都有object的属性和方法

5.2 内置函数dir()可以查看那指定对象的所有属性

5.3 object类有一个__str__()方法,用于返回一个对于“对象的描述”,对应于内置函数str()经常用于print()方法,帮助我们查看对象的信息,所以我们经常会对__str__()重写

class Student():def __init__(self, name, age, stu_no):self.name = nameself.age = ageself.stu_no = stu_nodef __str__(self):return '我的名字是{}. 年龄是{}'.format(self.name, self.age)stu = Student('张三', 20, '1001')
print(stu)  # 默认会调用__str__()方法
print(type(stu))

6、特殊方法和特殊属性

6.1 特殊属性例子

class A:passclass B:passclass C(A, B):def __init__(self, name, age):self.name = nameself.age = age# 创建C类的对象
x = C('Jack', 22)
print(x.__dict__)  # 实例对象的属性字典
print(C.__dict__)  # 类对象属性和方法的字典
print(x.__class__)  # 输出了对象所属的类
print(C.__bases__)  # 输出C类的父类类型的元素
print(C.__base__)  # 输出类的基类(离C类最近的父类,即继承时谁在前就输出谁)
print(C.__mro__)  # 查看类的层次结构
print(A.__subclasses__())  # 查看所有的子类列表>>>>
{'name': 'Jack', 'age': 22}
{'__module__': '__main__', '__init__': <function C.__init__ at 0x0000029D494D7B70>, '__doc__': None}
<class '__main__.C'>
(<class '__main__.A'>, <class '__main__.B'>)
<class '__main__.A'>
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
[<class '__main__.C'>]

6.2 特殊方法__add__()和__len__()例子

class Student:def __init__(self, name):self.name = namedef __add__(self, other):return self.name + other.namedef __len__(self):return len(self.name)# __add__()的使用
stu1 = Student('张三')
stu2 = Student('李四')
s = stu1 + stu2  # 实现了两个对象的加法运算,因为在Student类中,编写了__add__()特殊方法
print(s)  # ==>张三李四
s2 =stu1.__add__(stu2)
print(s2)  # ==>张三李四# __len__()的使用
lst = [11, 22, 33, 44]
print(len(lst))  # len()是内置函数
print(len(stu1))
print(lst.__len__())  # 输出一个对象的长度

6.3 特殊方法__new__()和__init__()例子

class Person(object):def __new__(cls, *args, **kwargs):  # 用于创建对象print('__new__被调用了,cls的id值为{}'.format(id(cls)))obj = super().__new__(cls)print('创建的对象的id为:{}'.format(id(obj)))return objdef __init__(self, name, age):  # __init__()用于对对象的属性进行初始化print('__init__被调用了,self的id值为{}'.format(id(self)))self.name = nameself.age = ageprint('object这个类对象的id为:{}'.format(id(object)))
print('Person这个类对象的id为:{}'.format(id(Person)))# 创建person的实例对象
per = Person('张三', 22)
print('per这个类对象的id为:{}'.format(id(per)))>>>>
object这个类对象的id为:1762837952
Person这个类对象的id为:3006101015880
__new__被调用了,cls的id值为3006101015880
创建的对象的id为:3006132499624
__init__被调用了,self的id值为3006132499624
per这个类对象的id为:3006132499624

7、类的浅拷贝和深拷贝

7.1 变量的赋值操作

只是形成两个变量,实际上还是指向同一个变量

7.2 浅拷贝

Python中的拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝,因此,源对象与拷贝对象会引用同一个子对象

7.3 深拷贝

使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同

class Cpu:passclass Disk:passclass Computer:def __init__(self, cpu, disk):self.cpu = cpuself.disk = disk# 变量的赋值:值相同,只是存放在不同变量中
cpu1 = Cpu()
cpu2 = cpu1
print(cpu2, id(cpu2))  # ==><__main__.Cpu object at 0x000001A4BB59B588> 1807029482888
print(cpu1, id(cpu1))  # ==><__main__.Cpu object at 0x000001A4BB59B588> 1807029482888disk = Disk()
computer = Computer(cpu1, disk)
# 浅拷贝
import copy
computer2 = copy.copy(computer)
print(computer, '---', computer.cpu, '-----', computer.disk)
print(computer2, '---', computer2.cpu, '-----', computer2.disk)  # 只有computer2的值和computer值不同,其余相同
# 深拷贝
computer3 = copy.deepcopy(computer)
print(computer, '---', computer.cpu, '-----', computer.disk)
print(computer3, '---', computer3.cpu, '-----', computer3.disk)  # computer3的结果和computer完全都不相同

8、模块

8.1 在python中一个扩展名为.py的文件就是一个模块,分为官方模块(os模块、sys模块、time模块、math模块),自定义模块,第三方模块(比如Web开发框架,Django、Flask,异步任务框架:Celery等)

8.2 模块与函数的关系:一个模块中可以包含N多个函数

8.3 使用模块的好处

① 方便其它程序和脚本的导入并使用

② 避免函数名和变量名冲突

③ 提高代码的可维护性

④ 提高代码的可重用性

8.4 模块导入的路径

>>> import sys
>>> sys.path
['', '/data/miniconda3/lib/python3.8', '/data/miniconda3/lib/python3.8/site-packages']

分析:

① 它返回的是一个列表,表示的是在搜索Python模块时,会搜索的路径

② 第一个路径是'',它是一个空字符串,表达的是当前路径的意思。

③ 第二个路径是/data/miniconda3/lib/python3.8,它是Python默认模块的存放的路径,在这个路径下,可以发现有os、sys等模块的代码。

④ 第三个路径是/data/miniconda3/lib/python3.8/site-packages,它是第三方模块代码的存放路径,在这个路径下,存放的是需要安装的第三方模块。

⑤ __init__.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名就是包的名称!比如说import arcpy的时候,arcpy是包的名称,实际上导入的是这个包文件夹下面的__init__.py文件。

⑥ Python有很多内置的包和模块可以不安装直接使用,非常方便,内置的包和模块都在$Python\Lib目录下面的,import一个模块之后便可以通过print来看出模块的位置。

8.5 自定义模块

① 创建模块:新建一个.py文件,名称尽量不要与python自带的标准模块名称相同

② 导入模块

import 模块名称 [as 别名]
from 模块名称 import 函数/变量/类

③ 以主程序形式运行:每个模块的定义中都包括一个记录模块名称的变量__name__,程序可以检查该变量,以确定在那个模块中执行。如果一个模块不是被导入到其他程序中执行,那么它可能在解释器的顶级模块中执行,顶级模块的__name__变量的值为__main__

if __name__ == '__main__':pass

8.6 import A和from A import B 执行过程浅析

① import A

  • 判断A模块是否已经被导入到sys.modules中了,(sys.modules中保存的是已经被导入过的模块),如果已经被导入了就不再导入,而是直接使用模块对象
  • 如果没有找到,python解释器就去sys.path中去搜索,如果没有找到,则抛出异常。
  • 根据模块文件A.py创建一个模块对象(和模块名一样)
  • 把模块对象的名字添加到本地作用域中(使用locals查看本地作用域的所有名字)
  • Reload:重新加载模块,对模块对象添加新属性(将新的属性添加到原有对象)

② from A import B

  • 判断A模块是否已经被导入过了 <sys.modules中保存是已经被导入过的模块>如果已经被导入了就不再导入而直接使用对象的属性
  • 如果没有找到 python就是去 sys.path 搜索 <创建空对象《和模块名是同名的》>,如果没有到 抛出异常
  • 根据模块文件A.py 导入到python解释器中 根据模块文件往对象中新增对应的属性
  • 把模块对象的属性名 添加到本地作用域
  • 查看本地作用域的所有名字<本地名字空间> locals()

③ 修改模块中的一个属性

  • 如果属性是不可变类型的

From A import B方式:在当前作用域只是保存的是模块对象A中属性B的引用,只会在当前作用域修改B的值,不会修改模块对象中的B属性的值

Import A方式:当前作用域保存的是模块对象的引用,所以能够修改 模块属性的值

  • 如果属性是可变类型的

from A import B方式:在当前作用域只是保存的是模块对象中属性B的引用 ,也就是说 B和A.B引用同样的数据,此时 如果在当前作用域修改B的值是能够修改属性的值。

Import A方式:当前作用保存的是模块对象的引用,修改的就是模块对象当中的属性的值,所以能够修改 模块属性的值

8.7 Python中常用的内置模块

8.8 离线批量下载安装模块包

① 导出需下载的模块包清单

#1.更换镜像源
# 将pip下载路径更改为清华镜像源(相比于国外网站网速更快)
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pip -U
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple#2.导出模块清单
# 第一种 导出所有第三方模块清单
pip freeze > requirements.txt
# 第二种 仅导出当前依赖项目的模块清单
python -m pip install pipreqs
pipreqs ./ --encoding=utf-8 --force#3.对清单中的模块进行批量更新
from pip._internal.utils.misc import get_installed_distributions
from subprocess import call
for dist in get_installed_distributions():call("pip install --upgrade --default-timeout=10000 --force " + dist.project_name, shell=True)#4.重新导出更新后的模块清单(步骤2)

② Python模块批下载方法

# wheel下载与download下载相结合:其中dirpath为自定义的模块保存路径。default-timeout是为了防止网速不稳定所引起的断点不续传问题
python -m pip --default-timeout=100 download  -d dirpath -r requirements.txt
python -m pip --default-timeout=100 wheel -r requirements.txt

③ Python模块批安装方法

# 自动安装模块包
python -m pip install --no-index --find-links=dirpath -r requirements.txt

9、包

9.1 Python中的包

① 包是一个分层次的目录结构,它将一组功能相近的模块组织在一个目录下。通俗来讲:包就是一个包含了init.py文件的文件夹(可以往该文件夹下放一堆子模块)

② 包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为__init__.py 文件,那么这个文件夹就称之为包有效避免模块名称冲突问题,让应用组织结构更加清晰

③ init.py 控制着包的导入行为

④ init.py为空仅仅是把这个包导入,不会导入包中的模块

⑤ all__在__init.py文件中,定义一个__all__变量,它控制着 from 包名 import *时导入的模块

9.2 作用

① 代码规范

② 避免模块名称冲突

9.3 包与目录的区别

① 包含__init__.py文件的目录称为包

② 目录中通常不包含__init__.py文件

9.4 包的导入

import 包名.模块名

① 导入一个包:导入一个package1,然后就可以直接使用init中的变量,使用from package1 import m1,就可以使用m1中的变量以及函数

② 导入一个包里的一个包:如果要使用package1里面的package2,同样导入package1.package2,然后就可以直接使用init中的变量,使用from package1.package2.m1 import f1,就可以使用m2中的变量以及函数

③ 绝对路径导入:使用from package1.m1 import f1

④ 相对路径导入:(只有在包内才能使用):from ..m1 import f1

⑤ sys.path 和sys.modules:sys.path包含了module的查找路径;sys.modules包含了当前所load的所有的modules的dict(其中包含了builtin的modules)

9.5 闭包

① 像这种内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。

② 闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。

③ 返回函数不要引用任何循环变量,或者后续会发生变化的变量。

#返回闭包不能引用循环变量,请改写count()函数,让它正确返回能计算1x1、2x2、3x3的函数

#返回闭包不能引用循环变量,请改写count()函数,让它正确返回能计算1x1、2x2、3x3的函数
def count():fs = []for i in range(1, 4):def f(j):def g():return j*jreturn gr = f(i)fs.append(r)return fs
f1, f2, f3 = count()
print(f1(), f2(), f3()) #==>(1, 4, 9) 

9.6 模块的打包

① 需要安装对应版本的setuptools模块,这是一个python的模块打包工具。(可以在pypi上找到)

② 打包准备

# 新建test.py文件,内容如下:
print("show me")# 新建一个setup.py编译文件,内容如下:
from distutils.core import setup
setup(name='Myblog',  #打包后的包文件名version='1.0',description='My Blog Distribution Utilities',author='Liu tiansi',author_email='liutiansi@gmail.com',url='http://blog.liuts.com',py_modules=['test'],   #与前面的新建文件名一致
)

③ 运行如下命令

python setup.py sdist #打包后的格式为tar.gz/zip

④ 运行结果:当前目录下新增一个dist目录,里面会有一个同name值相同的文件包。Windows下时zip包,linux下是tar.gz包。

⑤ 安装:解压刚打包好的文件,运行如下命令进行安装:

python setup.py install

⑥ 测试:进入python解释器环境,运行如下命令,如果成功打印出show me字样则表示成功

import test

⑦ 卸载:

python setup.py uninstall

10、库

10.1 库定义

① python 的一个项目

10.2 标准库

① python 安装时自带的库

10.3 第三方库

① 所有 pythoner 开发经过审核后作为第三方库

10.4 自定义库

① 项目名

11、总结

11.1 关于包和模块

① 模块:是一个单独的.py文件,用于存放一些功能相关的代码,可以是代码更加容易维护,提高代码的重用价值

② 包:是一个有层级的目录结构,包含n个模块或者n个子包,包中一定要有__init__.py文件

③ 库:是完成一定功能的代码集合,表现形式是一个模块,或包

④ 框架:是一个架构层面的概念,为解决一个开放性问题而设计的具有一定约束性的支撑结构,通过框架可以快速实现一个解决问题的骨架,后面按照框架中的角色去填充和交互,就可以完成质量高,维护性强的项目

⑤ 包和模块的作用:1.有效的对程序进行分解,方便代码的管理和维护,如造一辆车,就得先造好轮子、发动机和壳等小的零件,再将这些小零件组合,就可以做成车,同样,拿模块和包过来就可以则合成大的程序;2.避免同一模块中命名重复问题

11.2 关于包和模块的分类

① 标准包和模块:安装python后自动下载在电脑中的包和模块,可以直接导入使用,满足用户基本的需求;其中有一些特殊的包和模块--内建包和模块,如builtins模块,其中包含了很多如print这样的常用的方法,所以内建包和模块不需要导入就可以直接使用

② 三方包和模块:别的程序员开发的包和模块,需要用户手动去相关网站上下载安装,然后进行导入使用

③ 自定义包和模块:用户自己写的一些好的包和模块

11.3 关于包和模块的分类

① 包和模块名:包名是包的名称,模块名是.py文件的名称

② 包和模块位置:可以通过“print(模块.__file__)”来查看包和模块的位置信息

③ 包和模块中的内容:可以通过“print(dir(模块))”来查看列出的包和模块中的内容

11.4 类与模块的区别

① 模块

  • 是数据/逻辑包
  • 通过编写Python文件和C扩展来创建
  • 通过导入import来使用

② 类

  • 实现新的对象
  • 由class语句创建
  • 通过调用来使用
  • 总是位于一个模块中
  • class中可以用def init(self,参数1,参数2,参数3)初始化

七、Python常见操作--文件操作/正则操作/日期操作/日志操作

1、文件操作

1.1 编码格式

① Python的解释器使用的时Unicode(内存)

② .py文件在磁盘上使用UTF-8存储(外存)

1.2 文件读写原理

① 文件的读写俗称‘IO操作’

② 文件读写操作流程

③ 操作原理

④ 内置函数open()创建文件对象:通过IO流将磁盘中的内容与程序的对象中的内容进行同步

⑤ 语法规则

1.3 常用的文件打开模式

① 文本文件:默认为Unicode字符集,可以用记事本打开

② 二进制文件:叭数据内容用‘字节’进行存储,无法用记事本打开,必须用专门的软件打开,比如mp3文件,jpg图片

③ 一个例子

# 创建一个文件,写入内容
file = open('a.txt', 'w')
file.write('python')
file.close()>>>>查看a.txt内容
python# 在刚才的文件内容上进行追加
file = open('a.txt', 'a')
file.write('python')
file.close()>>>>查看a.txt内容
pythonpython# 对二进制文件的操作
file1 = open('logo.jpg', 'rb')
file2 = open('copylogo.jpg', 'wb')
# 边读编写
file2.write(file1.read())
file2.close()
file1.close()

④ 常见的文件打开模式


1.4 文件对象的常用方法

### 关于操作的例子
file = open('1.txt', 'r')
# 读取全部内容
print(file.read())
# 读取一行
print(file.readline())
# 读取每一行
print(file.readlines())# 追加一个字符
file = open('1.txt', 'a')
file.write('hello')# 追加一个列表
file = open('1.txt', 'a')
lis = ['java', 'c++']
file.writelines(lis)file = open('1.txt', 'r')
file.seek(2)  # 从第二位开始读(第一位为0)
print(file.read())
print(file.tell())  # 获取当前指针位置file = open('2.txt', 'a')
file.write('hello')
file.flush()
file.write('world')# 切记以上每一步完成后都必须要关闭文件,不然万一出错后,文件就不能正确关闭了
file.close()

1.5 with语句(上下文管理器)

① with语句可以自动管理上下文资源,不论什么原因跳出with块,都能确保文件正确的关闭,以此来达到释放资源的目的

② with语句解释

1.6 目录操作(OS)

① os模块时Python内置的与操作系统功能和文件系统相关的模块

② 在不同的操作系统上运行,得到的结果可能不一样

③ os模块和os.path模块用于对目录或文件进行操作

import os# 打开系统应用计算器
os.system('calc.exe')  # 打开系统应用计算器
# 直接调用可执行文件
os.startfile('D:\\Program Files (x86)\\Tencent\\QQ\\Bin\\qq.exe')

④ os模块操作目录相关函数        

import os# 打印当前文件所在的路径
print(os.getcwd())
# 返回文件所在文件夹下的所有文件
lst = os.listdir('../test')
print(lst)
# 新建一个目录(文件夹)
os.mkdir('练习')
os.makedirs('练习1/练习2/练习3')
# 删除
os.rmdir('练习')
os.removedirs('练习1/练习2/练习3')# 遍历一个文件夹下所有的内容(包括文件夹和文件)
import os
path = os.getcwd()
lst_file = os.walk(path)
for dirpath, dirname, filename in lst_file:for dir in dirname:print(os.path.join(dirpath, dir))for file in filename:print(os.path.join(dirpath, file))

1.7 os.path模块的常用方法

函数 描述
abspath(path) 用于获取文件或目录的绝对路径
exists(path) 用于判断文件或目录是否存在,如果存在返回True,否则返回False
join(path, name) 将目录与目录或者文件名拼接起来
splitext() 分离文件名和扩展名
basename(path) 从一个目录中提取文件名
dirname(path) 从一个路径中提取文件路径,不包括文件名
isdir(path) 用于判断是否为路径,是返回True
import os.pathprint(os.path.abspath('test.py'))
print(os.path.exists('test.py'))
print(os.path.exists('test1.py'))
print(os.path.join('C:\\python', 'domo.py'))
print(os.path.split('C:\\Users\\Administrator\\Desktop\\test\\test.py'))
print(os.path.splitext('test.py'))
print(os.path.basename('C:\\Users\\Administrator\\Desktop\\test\\test.py'))
print(os.path.dirname('C:\\Users\\Administrator\\Desktop\\test\\test.py'))
print(os.path.isdir('C:\\Users\\Administrator\\Desktop\\test\\test.py'))>>>>
C:\Users\Administrator\Desktop\test\test.py
True
False
C:\python\domo.py
('C:\\Users\\Administrator\\Desktop\\test', 'test.py')
('test', '.py')
test.py
C:\Users\Administrator\Desktop\test
False # 列出指定目录下的所有py文件
import os
path = os.getcwd()
lst = os.listdir(path)
for filename in lst:if filename.endswith('.py'):print(filename)

2、正则操作(主要是re 模块)

2.1 基本语法

2.2 re模块

① compile 函数:compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。语法格式为:re.compile(pattern[, flags])

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import repattern = re.compile(r'\d+')  # 用于匹配至少一个数字
m = pattern.match('one12twothree34four')  # 查找头部,没有匹配
print(m)  # ==> Nonem = pattern.match('one12twothree34four', 2, 10)  # 从'e'的位置开始匹配,没有匹配
print(m)  # ==> Nonem = pattern.match('one12twothree34four', 3, 10)  # 从'1'的位置开始匹配,正好匹配
print(m)  # ==> <_sre.SRE_Match object; span=(3, 5), match='12'>
print(m.group())  # ==> 12
print(m.start())  # ==> 3
print(m.end())  # ==> 5
print(m.span())  # ==> (3, 5)

在上面,当匹配成功时返回一个 Match 对象,其中:

  • group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group() 或 group(0);
  • start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;
  • end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;
  • span([group]) 方法返回 (start(group), end(group))
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import repattern = re.compile(r'([a-z]+) ([a-z]+)', re.I)  # re.I 表示忽略大小写
m = pattern.match('Hello World Wide Web')
print(m)  # 匹配成功,返回一个 Match 对象  # ==> <_sre.SRE_Match object; span=(0, 11), match='Hello World'>
print(m.group(0))  # 返回匹配成功的整个子串    # ==> Hello World
print(m.span(0))  # 返回匹配成功的整个子串的索引  # ==> (0, 11)print(m.group(1))  # 返回第一个分组匹配成功的子串 # ==> Hello
print(m.span(1))  # 返回第一个分组匹配成功的子串的索引   # ==> (0, 5)print(m.group(2))  # 返回第二个分组匹配成功的子串 # ==> World
print(m.span(2))  # 返回第二个分组匹配成功的子串索引    # ==> (6, 11)print(m.group())  # 等价于 (m.group(1), m.group(2), ...)   # ==> Hello World
print(m.group(3))  # 不存在第三个分组   # ==> IndexError: no such group

② re.match函数:re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。函数语法:re.match(pattern, string, flags=0)

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import reprint(re.match('www', 'www.runoob.com').span())  # 在起始位置匹配  # ==> (0, 3)
print(re.match('com', 'www.runoob.com'))  # 不在起始位置匹配    # ==> Noneline = "Cats are smarter than dogs"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
# (.*?) 表示"非贪婪"模式,只保存第一个匹配到的子串
matchObj = re.match(r'(.*) are (.*?) .*', line, re.M | re.I)if matchObj:print("matchObj.group() : ", matchObj.group())  # ==> matchObj.group() :  Cats are smarter than dogsprint("matchObj.group(1) : ", matchObj.group(1))    # ==> matchObj.group(1) :  Catsprint("matchObj.group(2) : ", matchObj.group(2))    # ==> matchObj.group(2) :  smarter
else:print("No match!!")

③ re.search方法:re.search 扫描整个字符串并返回第一个成功的匹配。函数语法:re.search(pattern, string, flags=0)

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import reprint(re.search('www', 'www.runoob.com').span())  # 在起始位置匹配 # ==> (0, 3)
print(re.search('com', 'www.runoob.com').span())  # 不在起始位置匹配    # ==> (11, 14)line = "Cats are smarter than dogs"searchObj = re.search(r'(.*) are (.*?) .*', line, re.M | re.I)if searchObj:print("searchObj.group() : ", searchObj.group())    # ==> searchObj.group() :  Cats are smarter than dogsprint("searchObj.group(1) : ", searchObj.group(1))  # ==> searchObj.group(1) :  Catsprint("searchObj.group(2) : ", searchObj.group(2))  # ==> searchObj.group(2) :  smarter
else:print("Nothing found!!")

④ re.sub(pattern, repl, string, count=0, flags=0):用于替换字符串中的匹配项。

参数:

  • pattern : 正则中的模式字符串。
  • repl : 替换的字符串,也可为一个函数。
  • string : 要被查找替换的原始字符串。
  • count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
  • flags : 编译时用的匹配模式,数字形式。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import rephone = "2004-959-559 # 这是一个电话号码"# 删除注释
num = re.sub(r'#.*$', "", phone)
print("电话号码 : ", num)  # ==> 电话号码 :  2004-959-559# 移除非数字的内容
num = re.sub(r'\D', "", phone)
print("电话号码 : ", num)  # ==> 电话号码 :  2004959559# 将匹配的数字乘于 2
def double(matched):value = int(matched.group('value'))return str(value * 2)s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))  # ==> A46G8HFD1134

⑤ findall:在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。注意: match 和 search 是匹配一次 findall 匹配所有。语法格式为:re.findall(pattern, string, flags=0)或pattern.findall(string[, pos[, endpos]])

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import reresult1 = re.findall(r'\d+', 'runoob 123 google 456')pattern = re.compile(r'\d+')  # 查找数字
result2 = pattern.findall('runoob 123 google 456')
result3 = pattern.findall('run88oob123google456', 0, 10)print(result1)  # ==> ['123', '456']
print(result2)  # ==> ['123', '456']
print(result3)  # ==> ['88', '12']

⑥ re.finditer:和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。re.finditer(pattern, string, flags=0)

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import reit = re.finditer(r"\d+", "12a32bc43jf3")
for match in it:print(match.group())
# ==> 12
# ==> 32
# ==> 43
# ==> 3

⑦ re.split:split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:re.split(pattern, string[, maxsplit=0, flags=0])

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import reprint(re.split('\W+', 'runoob, runoob, runoob.')) # ==> ['runoob', 'runoob', 'runoob', '']
print(re.split('(\W+)', ' runoob, runoob, runoob.'))    # ==> ['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', '']
print(re.split('\W+', ' runoob, runoob, runoob.', 1))   # ==> ['', 'runoob, runoob, runoob.']
print(re.split('a*', 'hello world'))    # 对于一个找不到匹配的字符串而言,split 不会对其作出分割 # ==> ['hello world']

⑧ re.fullmatch:如果整个 string 匹配到正则表达式样式,就返回一个相应的匹配对象;否则就返回一个 None。形式如下:re.fullmatch(pattern, string, flags=0)

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import reprint(re.fullmatch(r'abc', 'abcef'))    # ==> None
print(re.fullmatch(r'abc', 'abc'))  # ==> <_sre.SRE_Match object; span=(0, 3), match='abc'>

⑨ re.subn:行为与 re.sub() 相同,但返回的是一个元组。形式如下:re.subn(pattern, repl, string, count=0, flags=0)

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import restr = 'ityard # 是我的名字'
print(re.subn(r'#.*$', '', str))  # ==> ('ityard ', 1)

⑩ re.escape(pattern):转义 pattern 中的特殊字符。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import reprint(re.escape('https://blog.csdn.net/ityard'))    # ==> https\:\/\/blog\.csdn\.net\/ityard

⑪ re.purge():清除正则表达式缓存。

2.3 正则对象

① Pattern.search(string[, pos[, endpos]]):扫描整个 string 寻找第一个匹配的位置,并返回一个相应的匹配对象,如果没有匹配,就返回 None;可选参数 pos 给出了字符串中开始搜索的位置索引,默认为 0;可选参数 endpos 限定了字符串搜索的结束

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import repattern = re.compile(r'bc', re.I)
print(pattern.search('aBcdef'))  # ==> <_sre.SRE_Match object; span=(1, 3), match='Bc'>
print(pattern.search('aBcdef', 1, 3))  # ==> <_sre.SRE_Match object; span=(1, 3), match='Bc'>

② Pattern.match(string[, pos[, endpos]]):如果 string 的开始位置能够找到这个正则样式的任意个匹配,就返回一个相应的匹配对象,如果不匹配,就返回 None

import repattern = re.compile(r'bc', re.I)
print(pattern.match('aBcdef'))  # ==> None
print(pattern.match('aBcdef', 1, 3))  # ==> <_sre.SRE_Match object; span=(1, 3), match='Bc'>

③ Pattern.fullmatch(string[, pos[, endpos]]):如果整个 string 匹配这个正则表达式,就返回一个相应的匹配对象,否则就返回 None

import repattern = re.compile(r'bc', re.I)
print(pattern.fullmatch('Bc'))  # ==> <_sre.SRE_Match object; span=(0, 2), match='Bc'>
print(pattern.fullmatch('aBcdef', 1, 3))  # ==> <_sre.SRE_Match object; span=(1, 3), match='Bc'>

④ Pattern.split(string, maxsplit=0):等价于 re.split() 函数,使用了编译后的样式

import repattern = re.compile(r'bc', re.I)
print(pattern.split('abc, aBcd, abcde.'))   # ==> ['a', ', a', 'd, a', 'de.']

⑤ Pattern.findall(string[, pos[, endpos]]):使用了编译后样式,可以接收可选参数 pos 和 endpos,限制搜索范围

import repattern = re.compile(r'bc', re.I)
print(pattern.findall('abcefabCdeABC'))  # ==> ['bc', 'bC', 'BC']
print(pattern.findall('abcefabCdeABC', 0, 6))  # ==> ['bc']

⑥ Pattern.finditer(string[, pos[, endpos]]):使用了编译后样式,可以接收可选参数 pos 和 endpos ,限制搜索范围

import repattern = re.compile(r'bc', re.I)
it = pattern.finditer('12bc34BC56', 0, 6)
for match in it:print(match)    # ==> <_sre.SRE_Match object; span=(2, 4), match='bc'>

⑦ Pattern.sub(repl, string, count=0):使用了编译后的样式

import repattern = re.compile(r'#.*$')
str = 'ityard # 是我的名字'
print(pattern.sub('', str))  # ==> ityard 

⑧ Pattern.subn(repl, string, count=0):使用了编译后的样式

import repattern = re.compile(r'#.*$')
str = 'ityard # 是我的名字'
print(pattern.subn('', str))  # ==> ('ityard ', 1)

2.4 匹配对象

① Match.expand(template):对 template 进行反斜杠转义替换并且返回

import rematch = re.match(r'(?P<year>\w+) (?P<month>\w+)', '2020 01')
print(match.expand(r'现在是 \1 年 \2 月'))  # ==> 现在是 2020 年 01 月

② Match.group([group1, ...]):返回一个或者多个匹配的子组

import rematch = re.match(r'(?P<year>\w+) (?P<month>\w+)', '2020 01')
print(match.group(0))  # ==> 2020 01
print(match.group(1))  # ==> 2020
print(match.group(2))  # ==> 01

③ Match.groups(default=None):返回一个元组,包含所有匹配的子组,在样式中出现的从 1 到任意多的组合,default 参数用于不参与匹配的情况,默认为 None

import rematch = re.match(r'(?P<year>\w+) (?P<month>\w+)', '2020 01')
print(match.groups())  # ==> ('2020', '01')

④ Match.groupdict(default=None):返回一个字典,包含了所有的命名子组,default 参数用于不参与匹配的组合,默认为 None

import rematch = re.match(r'(?P<year>\w+) (?P<month>\w+)', '2020 01')
print(match.groupdict())  # ==> {'year': '2020', 'month': '01'}

⑤ Match.start([group]) 和 Match.end([group]):返回 group 匹配到的字串的开始和结束标号

import rematch = re.match(r'(?P<year>\w+) (?P<month>\w+)', '2020 01')
print(match.start())  # ==> 0
print(match.end())  # ==> 7

⑥ Match.span([group]):对于一个匹配 m,返回一个二元组 (m.start(group), m.end(group))

import rematch = re.match(r'(?P<year>\w+) (?P<month>\w+)', '2020 01')
print(match.span())  # ==> (0, 7)

2.5 正则表达式对象

① re.RegexObject:re.compile() 返回 RegexObject 对象

② re.MatchObject:group() 返回被 RE 匹配的字符串。

  • start() 返回匹配开始的位置
  • end() 返回匹配结束的位置
  • span() 返回一个元组包含匹配 (开始,结束) 的位置

③ 贪婪和非贪婪

在匹配次数不确定的时候,匹配模式分为贪婪和非贪婪两种,默认是贪婪模式。

在匹配成功的前提下,贪婪是匹配次数选最多的那个次数;非贪婪是匹配次数最少的那个次数。

贪婪的:*、+、?、{M,N}、{M,}、{,N}

非贪婪的:*?、+?、??、{M,N}?、{M,}?、{,N}?

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import reprint(re.match(r'\d{3}', '123这是一个练习题adsfbag'))  # ==> <_sre.SRE_Match object; span=(0, 3), match='123'>
print(re.match(r'a.*b', 'adsfabg这是一个练习题'))  # ==> <_sre.SRE_Match object; span=(0, 6), match='adsfab'>
print(re.match(r'a.*?b', 'adsfabg这是一个练习题adsfag'))  # ==> <_sre.SRE_Match object; span=(0, 6), match='adsfab'>print(re.match(r'a.*b', 'adsfbag这是一个练习题adsfag'))  # ==> <_sre.SRE_Match object; span=(0, 5), match='adsfb'>
print(re.match(r'a.*?b', 'adsfagb这是一个练习题adsfag'))  # ==> <_sre.SRE_Match object; span=(0, 7), match='adsfagb'>

2.6 正则表达式修饰符 - 可选标志

正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:

2.7 正则表达式实例

① 字符匹配

② 字符类

③ 特殊字符类

实例 描述
. 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式
\d 匹配一个数字字符。等价于 [0-9]
\D 匹配一个非数字字符。等价于 [^0-9]
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]
\w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'
\W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'

2.8 常见的几个正则匹配

① 指定字符出现的次数

#!/usr/bin/python
# -*- coding: UTF-8 -*-
s = "Count, the number of spaces."
print(s.count(" "))  # ==> 4
x = "I like to program in Python"
print(x.count("i"))  # ==> 2

② 匹配电子邮箱的规则

import retext = '112233445aass@163.com'
if re.match(r'^[0-9a-zA-Z_]{0,19}@[0-9a-zA-Z]{1,13}\.[com,cn,net]{1,3}$', text):print('Right!')
else:print('Error!')

③ URL合法性验证

import reipAddr = '10.10.123.23'
compile_ip = re.compile('^(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)$')
if compile_ip.match(ipAddr):print('right!')
else:print('error!')

④ 匹配日期

import retest_err_date = '如这样的日期2020-8-8也可以匹配到.测试如下.'
print(re.search(r"(\d{4}-\d{1,2}-\d{1,2})", test_err_date).group(0))

3、日志操作

3.1 日志概述

① 日志的等级:DEBUG、INFO、NOTICE、WARNING、ERROR、CRITICAL、ALERT、EMERGENCY、

② 日志字段信息:事件发生时间、事件发生位置、事件的严重程度--日志级别、事件内容

③ 日志功能的实现:Python自身也提供了一个用于记录日志的标准库模块--logging

3.2 logging模块

① logging模块的日志级别

② 日志等级:上面列表中的日志等级是从上到下依次升高的,DEBUG < INFO < WARNING < ERROR < CRITICAL,而日志的信息量是依次减少的

③ logging模块定义的模块级别的常用函数

④ logging模块的四大组件

3.3 使用logging提供的模块级别的函数记录日志

① 可以通过logging模块定义的模块级别的方法去完成简单的日志记录

② 只有级别大于或等于日志记录器指定级别的日志记录才会被输出,小于该级别的日志记录将会被丢弃

③ 输出一条不同日志级别的日志记录

## 方式一
import logginglogging.debug("This is a debug log.")
logging.info("This is a info log.")
logging.warning("This is a warning log.")
logging.error("This is a error log.")
logging.critical("This is a critical log.")## 方式二
logging.log(logging.DEBUG, "This is a debug log.")
logging.log(logging.INFO, "This is a info log.")
logging.log(logging.WARNING, "This is a warning log.")
logging.log(logging.ERROR, "This is a error log.")
logging.log(logging.CRITICAL, "This is a critical log.")

④ logging模块提供的日志记录函数所使用的日志器设置的日志级别是WARNING,因此只有WARNING级别的日志记录以及大于它的ERROR和CRITICAL级别的日志记录被输出了,而小于它的DEBUG和INFO级别的日志记录被丢弃了。

⑤ 上面输出结果中每行日志记录的各个字段含义分别是:日志级别:日志器名称:日志内容;因为logging模块提供的日志记录函数所使用的日志器设置的日志格式默认是BASIC_FORMAT,其值为:"%(levelname)s:%(name)s:%(message)s"

⑥ logging模块提供的日志记录函数所使用的日志器设置的处理器所指定的日志输出位置默认为:sys.stderr

3.4 logging.basicConfig()函数

① 该方法用于为logging日志系统做一些基本配置,方法定义如下:logging.basicConfig(**kwargs)

② 该函数可接收的关键字参数如下:

③ logging.basicConfig()函数是一个一次性的简单配置工具使,也就是说只有在第一次调用该函数时会起作用,后续再次调用该函数时完全不会产生任何操作的,多次调用的设置并不是累加操作

④ 日志器(Logger)是有层级关系的,上面调用的logging模块级别的函数所使用的日志器是RootLogger类的实例,其名称为'root',它是处于日志器层级关系最顶层的日志器,且该实例是以单例模式存在的

⑤ 如果要记录的日志中包含变量数据,可使用一个格式字符串作为这个事件的描述消息(logging.debug、logging.info等函数的第一个参数),然后将变量数据作为第二个参数*args的值进行传递,如:logging.warning('%s is %d years old.', 'Tom', 10),输出内容为WARNING:root:Tom is 10 years old.

3.5 logging模块定义的格式字符串字段

字段/属性名称 使用格式 描述
asctime %(asctime)s 日志事件发生的时间--人类可读时间,如:2003-07-08 16:49:45,896
created %(created)f 日志事件发生的时间--时间戳,就是当时调用time.time()函数返回的值
relativeCreated %(relativeCreated)d 日志事件发生的时间相对于logging模块加载时间的相对毫秒数(目前还不知道干嘛用的)
msecs %(msecs)d 日志事件发生事件的毫秒部分
levelname %(levelname)s 该日志记录的文字形式的日志级别('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')
levelno %(levelno)s 该日志记录的数字形式的日志级别(10, 20, 30, 40, 50)
name %(name)s 所使用的日志器名称,默认是'root',因为默认使用的是 rootLogger
message %(message)s 日志记录的文本内容,通过 msg % args计算得到的
pathname %(pathname)s 调用日志记录函数的源码文件的全路径
filename %(filename)s pathname的文件名部分,包含文件后缀
module %(module)s filename的名称部分,不包含后缀
lineno %(lineno)d 调用日志记录函数的源代码所在的行号
funcName %(funcName)s 调用日志记录函数的函数名
process %(process)d 进程ID
processName %(processName)s 进程名称,Python 3.1新增
thread %(thread)d 线程ID
threadName %(thread)s 线程名称

3.6 日志输出

① 配置日志器的日志级别

import logginglogging.basicConfig(level=logging.DEBUG)logging.debug("This is a debug log.")
logging.info("This is a info log.")
logging.warning("This is a warning log.")
logging.error("This is a error log.")
logging.critical("This is a critical log.")#输出结果:
#DEBUG:root:This is a debug log.
#INFO:root:This is a info log.
#WARNING:root:This is a warning log.
#ERROR:root:This is a error log.
#CRITICAL:root:This is a critical log.

② 配置日志输出目标文件和日志格式

import loggingLOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
logging.basicConfig(filename='my.log', level=logging.DEBUG, format=LOG_FORMAT)logging.debug("This is a debug log.")
logging.info("This is a info log.")
logging.warning("This is a warning log.")
logging.error("This is a error log.")
logging.critical("This is a critical log.")#结果:发现控制台中已经没有输出日志内容了,但是在python代码文件的相同目录下会生成一个名为'my.log'的日志文件,该文件中的内容为:
#2017-05-08 14:29:53,783 - DEBUG - This is a debug log.
#2017-05-08 14:29:53,784 - INFO - This is a info log.
#2017-05-08 14:29:53,784 - WARNING - This is a warning log.
#2017-05-08 14:29:53,784 - ERROR - This is a error log.
#2017-05-08 14:29:53,784 - CRITICAL - This is a critical log.

③ 配置日期/时间格式

import loggingLOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p"logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT, datefmt=DATE_FORMAT)logging.debug("This is a debug log.")
logging.info("This is a info log.")
logging.warning("This is a warning log.")
logging.error("This is a error log.")
logging.critical("This is a critical log.")#输出结果:
#08/08/2021 19:49:40 PM - DEBUG - This is a debug log.
#08/08/2021 19:49:40 PM - INFO - This is a info log.
#08/08/2021 19:49:40 PM - WARNING - This is a warning log.
#08/08/2021 19:49:40 PM - ERROR - This is a error log.
#08/08/2021 19:49:40 PM - CRITICAL - This is a critical log.

4、时间和日期操作

4.1 时间的表现形式

① 常见的时间表示形式为:时间戳、格式化的时间字符串

② Python中还有其它的时间表示形式:time模块的time.struct_time & datetime模块的datetime类

③ time.struct_time包含如下属性

④ 属性值的获取方式有两种:

  • 可以把它当做一种特殊的有序不可变序列通过 下标/索引 获取各个元素的值,如t[0]
  • 也可以通过 .属性名 的方式来获取各个元素的值,如t.tm_year。

⑤ 需要说明的是struct_time实例的各个属性都是只读的,不可修改。

4.2 time模块

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import time# 获取时间戳格式的时间
print(time.time())  # ==> 1628427001.9826148
# 获取struct_time格式的时间
print(time.localtime())  # ==> time.struct_time(tm_year=2021, tm_mon=8, tm_mday=8, tm_hour=20, tm_min=50, tm_sec=1, tm_wday=6, tm_yday=220, tm_isdst=0)
print(time.gmtime())  # ==> time.struct_time(tm_year=2021, tm_mon=8, tm_mday=8, tm_hour=20, tm_min=50, tm_sec=1, tm_wday=6, tm_yday=220, tm_isdst=0)
# 获取字符串格式的时间
print(time.ctime())  # ==> Sun Aug  8 20:50:01 2021
print(time.asctime())  # ==> Sun Aug  8 20:50:01 2021
print(time.strftime('%Y-%m-%d'))  # ==> 2021-08-08
# 时间戳格式转struct_time格式时间
t1 = time.time()
print(t1)  # ==> 1628427001.9826148
t2 = time.localtime(t1)
print(t2)  # ==> time.struct_time(tm_year=2021, tm_mon=8, tm_mday=8, tm_hour=20, tm_min=50, tm_sec=1, tm_wday=6, tm_yday=220, tm_isdst=0)
t3 = time.gmtime(t1)
print(t3)  # ==> time.struct_time(tm_year=2021, tm_mon=8, tm_mday=8, tm_hour=12, tm_min=50, tm_sec=1, tm_wday=6, tm_yday=220, tm_isdst=0)
# 字符串格式转struct_time格式时间
time1 = time.strptime('Sat Feb 04 14:06:42 2017')
print(time1)  # ==> time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=14, tm_min=6, tm_sec=42, tm_wday=5, tm_yday=35, tm_isdst=-1)
time2 = time.strptime('Sat Feb 04 14:06:42 2017', '%a %b %d %H:%M:%S %Y')
print(time2)  # ==> time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=14, tm_min=6, tm_sec=42, tm_wday=5, tm_yday=35, tm_isdst=-1)
time3 = time.strptime('2017-02-04 14:12', '%Y-%m-%d %H:%M')
print(time3)  # ==> time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=14, tm_min=12, tm_sec=0, tm_wday=5, tm_yday=35, tm_isdst=-1)
time4 = time.strptime('2017/02/04 14:12', '%Y/%m/%d %H:%M')
print(time4)  # ==> time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=14, tm_min=12, tm_sec=0, tm_wday=5, tm_yday=35, tm_isdst=-1)
time5 = time.strptime('201702041412', '%Y%m%d%H%M')
print(time5)  # ==> time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=14, tm_min=12, tm_sec=0, tm_wday=5, tm_yday=35, tm_isdst=-1)
# struct_time格式转字符串格式时间
t4 = time.strftime('%Y-%m-%d %H:%M', time.localtime())
print(t4)  # ==> 2021-08-08 20:50
# struct_time格式转时间戳格式时间
t5 = time.mktime(time.localtime())
print(t5)  # ==> 1628427002.0

4.3 时间格式转换

4.4 datetime模块

① datetime模块中定义的类

② datetime模块中定义的常量

4.5 datetime.date类

① 定义:class datetime.date(year, month, day);year, month 和 day都是是必须参数

② 类方法和属性

③ 对象方法和属性

④ 练习

import time
from datetime import dateprint(date.max)  # ==> 9999-12-31
print(date.min)  # ==> 0001-01-01
print(date.resolution)  # ==> 1 day, 0:00:00
print(date.today())  # ==> 2021-08-08
print(date.fromtimestamp(time.time()))  # ==> 2021-08-08d = date.today()
print(d.year)  # ==> 2021
print(d.month)  # ==> 8
print(d.day)  # ==> 8
print(d.replace(2008))  # ==> 2008-08-08
print(d.replace(2008, 5))  # ==> 2008-05-08
print(d.replace(2008, 5, 12))  # ==> 2008-05-12
print(d.timetuple())  # ==> time.struct_time(tm_year=2021, tm_mon=8, tm_mday=8, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=220, tm_isdst=-1)
print(d.toordinal())  # ==> 738010
print(d.weekday())  # ==> 6
print(d.isocalendar())  # ==> (2021, 31, 7)
print(d.isoformat())  # ==> 2021-08-08
print(d.ctime())  # ==> Sun Aug  8 00:00:00 2021
print(d.strftime('%Y/%m/%d'))  # ==> 2021/08/08

4.6 datetime.time类

① time类的定义:class datetime.time(hour, [minute[, second, [microsecond[, tzinfo]]]]);hour为必须参数,其他为可选参数

② 类方法和属性

③ 对象方法和属性

④ 练习

from datetime import timeprint(time.max)  # ==> 23:59:59.999999
print(time.min)  # ==> 00:00:00
print(time.resolution)  # ==> 0:00:00.000001t = time(21, 8, 10, 8888)
print(t.hour)  # ==> 21
print(t.minute)  # ==> 8
print(t.second)  # ==> 10
print(t.microsecond)  # ==> 8888
print(t.tzinfo)  # ==> None
print(t.replace(22))  # ==> 21:08:10.008888
print(t.isoformat())  # ==> 21:08:10.008888
print(t.strftime('%H%M%S'))  # ==> 210810
print(t.strftime('%H%M%S.%f'))  # ==> 210810

4.7 datetime.datetime类

① datetime类的定义:class datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None);year, month 和 day是必须要传递的参数, tzinfo可以是None或tzinfo子类的实例

② 类方法和属性

③ 对象方法和属性

④ 练习

#!/usr/bin/python
# -*- coding: UTF-8 -*-
from datetime import datetime, timezoneprint(datetime.today())  # ==> 2021-08-08 21:35:29.291769
print(datetime.now())  # ==> 2021-08-08 21:35:29.291769
print(datetime.now(timezone.utc))  # ==> 2021-08-08 13:35:29.291769+00:00
print(datetime.utcnow())  # ==> 2021-08-08 13:35:29.291769import timeprint(datetime.fromtimestamp(time.time()))  # ==> 2021-08-08 21:35:29.291769
print(datetime.utcfromtimestamp(time.time()))  # ==> 2021-08-08 21:35:29.291769
from datetime import *print(datetime.combine(date(2008, 5, 12), time(19, 46, 5), ))  # ==> 2008-05-12 19:46:05
print(datetime.strptime('2017/02/04 20:49', '%Y/%m/%d %H:%M'))  # ==> 2017-02-04 20:49:00dt = datetime.now()
print(dt)  # ==> 2021-08-08 21:44:47.593230
print(dt.year)  # ==> 2021
print(dt.month)  # ==> 8
print(dt.day)  # ==> 8
print(dt.hour)  # ==> 21
print(dt.minute)  # ==> 49
print(dt.second)  # ==> 21
print(dt.microsecond)  # ==> 482332
print(dt.tzinfo)  # ==> None
print(dt.timestamp())  # ==> 1628430561.482332
print(dt.date())  # ==> 2021-08-08
print(dt.time())  # ==> 21:49:21.482332
print(dt.timetz())  # ==> 21:49:21.482332
print(dt.replace())  # ==> 2021-08-08 21:49:21.482332
print(dt.replace(2222))  # ==> 2222-08-08 21:49:21.482332
print(dt.timetuple())  # ==> time.struct_time(tm_year=2021, tm_mon=8, tm_mday=8, tm_hour=21, tm_min=49, tm_sec=21, tm_wday=6, tm_yday=220, tm_isdst=-1)
print(dt.utctimetuple())  # ==> time.struct_time(tm_year=2021, tm_mon=8, tm_mday=8, tm_hour=21, tm_min=49, tm_sec=21, tm_wday=6, tm_yday=220, tm_isdst=0)
print(dt.toordinal())  # ==> 738010
print(dt.weekday())  # ==> 6
print(dt.isocalendar())  # ==> 2021-08-08T21:49:21.482332
print(dt.isoformat())  # ==> 2021-08-08T21:49:21.482332
print(dt.isoformat(sep='/'))  # ==> 2021-08-08/21:49:21.482332
print(dt.isoformat(sep=' '))  # ==> 2021-08-08 21:49:21.482332
print(dt.ctime())  # ==> Sun Aug  8 21:49:21 2021
print(dt.strftime('%Y%m%d %H:%M:%S.%f'))  # ==> 20210808 21:49:21.482332

4.8 datetime.timedelta类

① datetime.timedelta类的定义:class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, hours=0, weeks=0);所有参数都是默认参数,因此都是可选参数

② 类属性

③ 实例方法和属性

④ 练习

import datetimeprint(datetime.timedelta(365).total_seconds())  # ==> 31536000.0
dt = datetime.datetime.now()
print(dt) # ==> 2021-08-08 22:00:49.080511
print(dt + datetime.timedelta(3))  # ==> 2021-08-11 22:00:49.080511
print(dt + datetime.timedelta(-3))  # ==> 2021-08-05 22:00:49.080511
print(dt + datetime.timedelta(hours=3))  # ==> 2021-08-09 01:00:49.080511
print(dt + datetime.timedelta(hours=-3))  # ==> 2021-08-08 19:00:49.080511
print(dt + datetime.timedelta(hours=3, seconds=30))  # ==> 2021-08-09 01:01:19.080511

Python基础篇 之开始学习叭相关推荐

  1. 经典Python面试题之Python基础篇

    Python基础篇 1. 为什么学习Python? 2. 通过什么途径学习的Python? 3. Python和Java.PHP.C.C#.C++等其他语言的对比? 4. 简述解释型和编译型编程语言? ...

  2. 杨洋python课程提高篇_杨洋老师:全民一起玩Python 基础篇+提高篇,老师幽默严谨不枯燥的学习编程...

    课程介绍 本套课程出自杨洋老师的全民一起玩Python 基础篇+提高篇官网售价299元,程保持了杨洋博士老师幽默严谨不枯燥的学习编程,清晰全面的授课风格,配有丰富的教学演示和插图.动画,是初学者学习P ...

  3. 面试题之第一部分(Python基础篇) 80题

    第一部分(python基础篇)80题 为什么学习Python?==*== # 1. python应用于很多领域,比如后端,前端,爬虫,机器学习(人工智能)等方面,几乎能涵盖各个开发语言的领域,同时它相 ...

  4. python包括哪些部分_第一部分 Python基础篇

    第⼀一部分 Python基础篇 1. 为什什么学习Python? 朋友推荐,比较简单易学,生态圈比较强大 发展趋势:人工智能.数据分析 2. 通过什什么途径学习的Python? 廖雪峰.网络博客.相关 ...

  5. pythondd_工程脚本插件方案 - c集成Python基础篇

    工程脚本插件方案 - c集成Python基础篇 序: 为何要集成脚本,怎样在工程中集成Python脚本. 在做比较大型的工程时,1般都会分核心层和业务层.核心层要求实现高效和稳定的基础功能,并提供调用 ...

  6. 杨洋python课程提高篇_杨洋老师《全民一起玩Python 基础篇+提高篇》

    全民一起玩Python 基础篇+提高篇 适用人群: 想用轻松系统的方式,从零开始真正理解掌握Python.进而学习办公.网抓.数据.AI.网站等技术的各界人士 课程概述: 制作精细.自带吐槽,每节课程 ...

  7. python基础篇{控制流语句}

    控制流语句 条件控制 单条件判断 多条件判断 练习 循环控制 while语句 for语句 range函数 练习 break 和 continue 语句 break语句 continue  python ...

  8. Python基础篇:你好,世界!

    Python基础篇:你好,世界! 开了一段时间的博客了,可能很多人都对Python基础不掌握或者掌握不牢固,所以我会分别出算法篇和基础篇的教程来教大家一步一步走向程序员的水平 接着我们看看下面这行代码 ...

  9. Python基础篇(七)

    Python基础篇(七) 前言 一.元组 1.1 元组的定义 1.2 元组的常见操作 二.字典 2.1 字典的语法 2.2 字典常见操作 2.3 字典的循环遍历 三.任务清单 3.1 基础练习 3.2 ...

最新文章

  1. Keras ImageDataGenerator用于数据扩充/增强的原理及方法
  2. 空缺的2018-3-11《祖宗十九代》《缝纫机乐队》
  3. 你了解的技术宅是这样吗?
  4. (转载)Xcode中other linker flags的作用
  5. fileviewpro绿色免安装版
  6. 如何提高SSD的使用寿命
  7. SEO:如何做好软文推广
  8. c语言字符加密向后四位_Base64加密?它只是一种编码算法,切勿用来加密
  9. Mybatis(3)-编写dao实现类的方式
  10. Python爬虫偷懒神器 — 快速构造请求头!
  11. java 5 多线程_Java基础系列五、多线程
  12. bzoj2440:[中山市选2011]完全平方数
  13. 福布斯牛人×××先生的两个概念
  14. 拓端tecdat|R语言:状态空间模型和卡尔曼滤波预测酒精死亡人数时间序列
  15. php-fpm stop,php-fpm 启动,重启,终止操作
  16. 让你一目了然的商业计划书
  17. 阿里 OSS AccessDenied You are denied by bucket referer policy.
  18. postgresql中recovery.conf分析
  19. SCI影响因子与期刊检索网站整理
  20. 【信息系统项目管理师学习笔记】10大管理|47个过程组:项目整体管理|制定项目章程

热门文章

  1. Lenovo/联想A628T root教程_方法
  2. h5用css换行怎么换,CSS 换行标签
  3. JS将字符串拆分为字符数组
  4. 计算机指令集_计算机科学组织| 指令集及其类型
  5. 霍尼韦尔与鱼跃医疗签署长期合作协议;云顶新耀向大中华区等引进mRNA新冠疫苗 | 医药健闻...
  6. GITHUB删除历史记录
  7. 技术培训班的一些见解
  8. Pandas数据分析⑥——数据分析实例(货品送达率与合格率/返修率/拒收率)
  9. “代理服务器拒绝连接“问题
  10. 电影摄影机2022年全球行业分析报告