Python经验总结

4 篇文章 0 订阅
2 篇文章 0 订阅

Python经验总结

Python的两种执行方式

一:交互式:即在终端输入运行.

在命令行输入指令,回车即可得到结果。步骤如下:

1:打开终端:winds命令为(wind+r)输入cmd,Linux 为:ctrl+alt+t

2:进入交互式:python3

3:编写代码:print(“hello world”)

4:离开交互式:exit()

二:文件式:即将指令编写到.py 文件,可以重复运行程序。

Python的常用文件编辑器Pycharm 的常用快捷键
快捷键功能
home 键移动到本行开头
end 键盘移动到本行末尾
ctrl + /注释或取消代码
ctrl +d复制行
鼠标左键 + alt选择列
shift + alt + 上下箭头移动行
Ctrl + Space智能提示

注释

给人看的,通常是对代码的描述信息。

1:单行注释:以#号开头。

2:多行注释:三引号开头,三引号结尾。

函数

表示一个功能,函数定义者是提供功能的人,函数调用者是使用功能的人。

例如:

1:print(数据) 作用:将括号中的内容显示在控制台中

2:变量 = input(“需要显示的内容”) 作用:将用户输入的内容赋值给变量

print() 函数及 input() 函数的用法如下 :
一 :input() 函数 :	1. 参数:提示的信息
				  2. 功能:让用户在终端中输入信息
				  3. 结果:用户输入的信息
				  4.= 赋值号 : 将右边的结果,复制一份给左边
result = input(" 请输入 ...:")
二 :print() 函数 :1. 参数:需要打印的信息
				 2. 功能:在终端中打印 ( 输出/显示 ) 信息
				 3. 结果:没有
print(" 你好,世界 ")

变量

1:定义:关联一个对象的标识符。即可以变化的数据:。

2:实际就是一个存放东东的盒子,可以向盒子里放任何东东。

3:建议命名:字母小写,多个单词以下划线隔开。:class_name

4:赋值:创建一个变量或改变一个变量关联的数据。即右边对象复制给左边 即(名称 = 对象)

5:语法:变量名 = 数据 ;变量名 1 = 变量名 2 = 数据;变量名 1, 变量名 2, = 数据 1, 数据 2

data01=input(' 请输入主角名字 :')   #无忌
data02 =input(' 请输入配角名字 :')  #翠山
temp = data01
# 将主角名字赋值给 temp 变量
data01 = data02
# 将配角名字赋值给 data01 变量
data02 = temp
# 将主角名字赋值给 temp 变量
print(data01) # 结果翠山
print(data02) # 结果无忌

del 语句:

1:语法:del 变量名 1, 变量名 2

2:作用:用于删除变量,同时解除与对象的关联.如果可能则释放对象。

3:自动化内存管理的引用计数:每个对象记录被变量绑定(引用)的数量,当为 0 时被销毁。

核心数据类型

1:在 python 中变量没有类型,但关联的对象有类型。

2:通过 type 函数可查看。

空值对象 None

1:表示不存在的特殊对象。

2:作用:占位和解除与对象的关联。即切断关系 / 占位

整形 int

1:表示整数,包含正数、负数、0。如: -5, 100, 0

2:字面值::十进制:5;二进制:0b 开头,后跟 1 或者 1;八进制:0o 开头,后跟 0~7;十六进制:0x 开头,

后跟 09,AF,a~f

3:小整数对象池:CPython 中整数 -5 至 256,永远存在小整数对象池中,不会被释放并可重复使用。

浮点型 float

1: 表示小数,包含正数、负数,0.0。

2:字面值:小数:1.0 ;2.5;科学计数法:e/E (正负号) 指数:1.23e-2 (等同于 0.0123);1.23456e5(等同于 123456.0)

字符串 str

是用来记录文本信息(文字信息)。字面值:双引号

复数 complex

由实部和虚部组成的数字。虚部是以 j 或 J 结尾。字面值: 1j 1+1j 1-1j

布尔 bool

用来表示真和假的类型

True 表示真(条件满足或成立),本质是 1;False 表示假(条件不满足或不成立),本质是 0

数据类型转换

1:转换为整形: int(数据)

2:转换为浮点型:float(数据)

3: 转换为字符串:str(数据)

4:转换为布尔:bool(数据):结果为 False:bool(0) bool(0.0) bool(None)

5:混合类型自动升级:1 + 2.14 返回的结果是 3.14;1 + 3.0 返回结果是: 4.0

运算符

算术运算符

+加法;- 减法;* 乘法;/ 除法:结果为浮点数;// 地板除:除的结果去掉小数部分;% 求余;** 幂运算

优先级从高到低: ();**;* / % //;+ -

增强运算符

获取一个整数各个位数的和方法 :如程序结果为 :10,1+2+3+4 的和。
方法一:
num = 1234
temp01 = num % 10          #取出:4
temp02 = num // 10 % 10    #取出:3
temp03 = num // 100 % 10   #取出:2
temp04 = num // 1000       #取出:1
result = temp01 + temp02 + temp03 + temp04 
print('结果是:' + str(result)) #结果是10
方法二:
num = 1234
result = num % 10
result += num // 10 % 10
result += num // 100 % 10
result += num // 1000
print('结果是:' + str(result)) #结果是10

比较运算符

符号功能
<小于
<=小于等于
>大于
>=大于等于
==等于
!=不等于

返回布尔类型的值:比较运算的数学表示方式:0 <= x <= 100

逻辑运算符:功能 : 判断命题 (bool 值 ) 关系

与 and:并且 : 一假俱假 , 表达的是 " 并且”的关系 ( 必须都满足 )

表示并且的关系,一假俱假。

示例:

True and True # True

True and False # False

False and True # False

False and False # False

或 or:一真俱真 , 表达的是 " 或者”的关系 ( 满足一个就行 )

表示或者的关系,一真俱真

示例:

True or True # True

True or False # True

False or True # True

False or False # False

非 not

表示取反

例如:

not True # 返回 False

not False # 返回 True

短路运算

一但结果确定,后面的语句将不再执行。启发:尽量将耗时的运算放在后面.

身份运算符

语法:

x is y

x is not y

作用:

is 用于判断两个对象是否是同一个对象,是时返回 True,否则返回 False。

is not 的作用与 is 相反

优先级

高到低:算数运算符 > 比较运算符 > 快捷运算符 > 身份运算符 > 逻辑运算符

1:物理行:程序员编写代码的行。

2:逻辑行:python 解释器需要执行的指令。

3:建议一个逻辑行在一个物理行上。

4:如果一个物理行中使用多个逻辑行,需要使用分号;隔开。

5:如果逻辑行过长,可以使用隐式换行或显式换行。

隐式换行:所有括号的内容换行,称为隐式换行;括号包括: () [] {} 三种

显式换行:通过折行符 \ (反斜杠)换行,必须放在一行的末尾,目的是告诉解释器,下一行也是本行的语句。

pass 语句

通常用来填充语法空白。

选择语句

If elif else 语句

1:作用:让程序根据条件选择性的执行语句。
2:语法:
if 条件 1:
语句块 1(满足条件 1 执行的代码 )
elif 条件 2:
语句块 2(满足条件 2 执行的代码 )
else:
语句块 3(以上都不满足执行的代码 )
3:说明:
elif 子句可以有 0 个或多个。
else 子句可以有 0 个或 1 个,且只能放在 if 语句的最后。

sex = input(" 请输入性别: ")
if sex == " 男 ":
	print(" 您好,先生! ")
elif sex == " 女 ":
	print(" 您好,女士! ")
else:
	print(" 性别未知 ")
# 如果是输入男 则 结果为 :您好 , 先生 !

if 语句的真值表达式

if 的真值表达式原理:
if 变量 :
变量存在数据则执行

if 100:
	print("真值")
等同于
if bool(100):
	print("真值")

条件表达式:有选择性的为变量进行赋值

语法:变量 = 结果 1 if 条件 else 结果 2
作用:根据条件(True/False) 来决定返回结果 1 还是结果 2。

循环语句

while 循环语句

1:作用:可以让一段代码满足条件,重复执行

2:语法:

​ while 条件:

​ 满足条件执行的语句

​ else:

​ 不满足条件执行的语句

3:说明:

else子句可以省略。在循环体内用 break 终止循环时,else 子句不执行

''''
     在控制台中获取一个开始值,一个结束值 .
     将中间的数字打印出来。
'''''
#方法一:
begin = int(input('请输入一个整数:'))
end = int(input('请输入一个整数:'))
if begin < end:
   count = begin +1
   while count <end:
       print(count)
       count +=1
else:
   count = begin- 1
   while count > end:
       print(count)
       count -= 1

#方法二
begin = int(input('请输入一个整数:'))
end = int(input('请输入一个整数:'))
dir =1 if end > begin else -1
while begin != end - dir:
    begin += dir
    # 循环如果开始值比最后值-1还小开始值加1.
    print(begin)
#若先输入1后输入5:则结果2 3 4 反之则结果4 3 2    

for 循环语句

1:作用:

​ 用来遍历可迭代对象的数据元素。可迭代对象是指能依次获取数据元素的对象,例如:容器类型。
2:语法:
​ for 变量列表 in 可迭代对象:
​ 语句块 1
​ else:
​ 语句块 2
3:说明:
​ else 子句可以省略。在循环体内用 break 终止循环时,else 子句不执行。

range 函数

1:作用:
用来创建一个生成一系列整数的可迭代对象(也叫整数序列生成器)。
2:语法:
range(开始点,结束点,间隔)
3:说明:
函数返回的可迭代对象可以用 for 取出其中的元素,返回的数字不包含结束点,开始点默认为 0,间隔默认值为 1

''''
    获取一个整数,作为边长。
    打印矩形。
    例如:边长4
    ****
    *  *
    *  *
    ****
    例如:边长6
    ******
    *    *
    *    *
    *    *
    *    *
    ******
'''''
count = int(input('请输入一个整数:'))
print('*'*count)                      #打印第一行
for i in range(count-2):              #循环打印中间行
    print('*' + ' ' *(count-2) +'*')  #前后一个*,中间空字符个数
print('*'*count)                      #打印最后一行

跳转语句

break 语句

功能:

​ 1:跳出循环体,后面的代码不再执行。
​ 2:可以让 while 语句的 else 部分不执行。

continue 语句

​ 跳过本次,继续下次循环。

1.range( 结束值 )
for item in range(5):# 0 1 2 3 4
	print(item)# 0 1 2 3 4
2. range( 开始值 , 结束值 )
for item in range(2,6):
	print(item)# 2 3 4 5
3. 倒序
for item in range(6,3,-1):
	print(item)  #6 5 4
4. 跳着
for item in range(2,11,2):
	print(item) #2 4 6 8 10
5. for + range 特别适合做预定次数的循环。
for item in range(50):
	print(item)
# 累加 1 -- 50 之间,能被 6 整除的数字 
方法一:
sum_value = 0
for item in range(1,51):
	if item % 6 == 0:
		sum_value += item
	print(sum_value)

方法二:
sum_value = 0
for item in range(5,51):
	if item % 6 != 0:
		continue
	sum_value += item
print(sum_value)

六大容器类型

可变系列容器:列表(list),字典(dict散列),集合(set去重)

不可变系列容器:字符串(str),元组(tuple),固定集合(frozenset)

通用操作

一:数学运算符

\1. +:用于拼接两个容器
\2. +=:用原容器与右侧容器拼接,并重新绑定变量
\3. *:重复生成容器元素
\4. *=:用原容器生成重复元素, 并重新绑定变量
\5. < <= > >= == !=:依次比较两个容器中元素,一但不同则返回比较结果。

二:成员运算符

1:语法:
数据 in 序列
数据 not in 序列
2: 作用:
如果在指定的序列中找到值,返回 bool 类型。

三:索引 index

1:作用:访问容器元素
2:语法:容器[整数]
3:说明:
正向索引从 0 开始,第二个索引为 1,最后一个为 len(s)-1。
反向索引从-1 开始,-1 代表最后一个,-2 代表倒数第二个,以此类推,第一个是-len(s)。

四:切片 slice

1:作用:
从容器中取出相应的元素重新组成一个容器。
2:语法:
容器[(开始索引):(结束索引)(:(步长))]
3:说明:
小括号()括起的部分代表可省略,结束索引不包含该位置元素,步长是切片每次获取完当前元素后移动的偏移量

五:内建函数

​ 1:len(x) 返回序列的长度
​ 2:max(x) 返回序列的最大值元素
​ 3:min(x) 返回序列的最小值元素
​ 4:sum(x) 返回序列中所有元素的和(元素必须是数值类型)

"""
str 通用操作
"""
#1. 数学运算符
# 拼接 + +=
str01 = " 悟空 " +" 八戒 "
print(id(str01))# 139637893711808
# 产生了新的字符串 " 悟空八戒唐僧 "
str01 += " 唐僧 "# 139637893711984
print(id(str01))
# 乘法 * :重复产生
str02 = " 白雪公主 "
str02 *= 10
print(str02) 结果 # 十个白雪公主
# 比较运算 < <= > >= == != :依次比较两个容器中元素 ,一但不同则返回比较结果
# 字符串比较的是编码值
str03 = "ac 悟空 "
str04 = "b 唐僧 "
print(str03 > str04) 结果 #False
# 2. 成员运算 : 作用 : 返回 bool 类型 .
re = " 八戒 " in str01
print(re) 结果 #True
# 3. 索引 : 定位单个元素
message = " 我叫齐天大圣。 "
# 获取第一个字符
print(message[0]) # 结果 : 我
print(message[-len(message)]) # 结果 : 我
# 获取最后一个字符
print(message[-1]) # 结果 :.
print(message[len(message)-1]) # 结果 :.
print(message[2:6]) # 结果 : 齐天大圣
print(message[2:6:2]) # 结果 : 齐大
# 开始索引,默认从头开始。
print(message[:6])# 结果 : 我叫齐天大圣
# 结束索引,默认到末尾。
print(message[2:])# 结果 : 齐天大圣。
# 正向获取
print(message[:])# 我叫齐天大圣。
# 反向获取
print(message[::-1])# 。圣大天齐叫我
print(message[-3:-6:-1])# 大天齐
# 可以同时使用反向与正向索引
print(message[-3:1:-1])# 大天齐
print(message[3:1])# 空
print(message[3:1:-1])# 天齐
print(message[1:1])# 空
print(message[-2:1])# 空
print(message[1:500])# 叫齐天大圣。
#判断是否回文
count = input('请输入一个字符串:')
if count[::-1] == count[:]:
    print('这个字符串是回文')
else:
    print('这个字符串不是回文')

字符串 str:存储字符的编码值,不可变序列。

定义

​ 由一系列字符组成的不可变序列容器,存储的是字符的编码值。拥有上述所有容器通用功能。

编码

​ 1:字节 byte:计算机最小存储单位,等于 8 位 bit.
​ 2:字符:单个的数字,文字与符号。
​ 3:字符集(码表):存储字符与二进制序列的对应关系。
​ 4:编码:将字符转换为对应的二进制序列的过程。
​ 5:解码:将二进制序列转换为对应的字符的过程。
​ 6:编码方式: 将字转换为数.
​ --ASCII 编码:包含英文、数字等字符,每个字符 1 个字节。
​ --GBK 编码:兼容 ASCII 编码,包含 21003 个中文;英文 1 个字节,汉字 2 个字节。
​ --Unicode 字符集:国际统一编码,旧字符集每个字符 2 字节,新字符集 4 字节。
​ – UTF-8 编码:Unicode 的存储与传输方式,英文 1 字节,中文 3 字节。

相关函数

​ 1:ord(字符串):返回该字符串的 Unicode 码。
​ 2:chr(整数):返回该整数对应的字符串。

# 数 --> 字
str01 = chr(97)
print(str01)

# 字 --> 数
number = ord("b")
print(number)
字面值
单引和双引号的区别

​ 1:单引号内的双引号不算结束符
​ 2: 双引号内的单引号不算结束符

三引号作用

​ 1:换行会自动转换为换行符\n
​ 2:三引号内可以包含单引号和双引号
​ 3: 作为文档字符串

转义字符

1:改变字符的原始含义。
\’ \” \””” \n \ \t \0 空字符
2:原始字符串:取消转义。
a = r”C:\newfile\test.py”

字符串格式化

1:定义:
生成一定格式的字符串。
2:语法:
字符串%(变量)
“我的名字是%s,年龄是%s” % (name, age)
3:类型码:
%s 字符串 %d 整数 %f 浮点数

字符串格式化的用法 :
name = " 孙悟空 "
age = 800
score = 85.6
str01 = " 我叫: " + name + " ,今年 :" + str(age) + " 岁,"
str02 = " 我叫: %s ,今年 :%d 岁,成绩是 :%.1f 。 "%(name, age, score)
print(str02)

字符串str常用操作:

一:判断

isspace()

​ 功能:如果字符串中只包含空白,则返回 True,否则返回 False.

startswith(substr, beg=0,end=len(string))

​ 功能:检查字符串是否是以指定子字符串 substr 开头,是则返回 True,否则返回 False。如果如果 beg和end 指定值,则在指定范围内检查。

endswith(suffix, beg=0, end=len(string))

​ 功能:检查字符串是否以 obj 结束,如果 beg 或者 end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回 False.

二:查找

find(str, beg=0 end=len(string))

​ 功能:检测 str 是否包含在字符串中,如果指定范围 beg 和 end ,则检查是否包含在指定范围内,如果包含返回 开始的索引值,否则返回 -1

rfind(str, beg=0,end=len(string))

​ 功能:类似于 find()函数,不过是从右边开始查找.

count(str, beg= 0,end=len(string))

​ 功能:返回 str 在 string 里面出现的次数,如果 beg 或者 end 指定则返回 指定范围内 str 出现的次数

三:修改

replace(old, new [, max])

​ 功能:把 将字符串中的 将字符串中的 str1 替换成 str2,如果 max 指定,则替换不超过 max 次。

lstrip()

​ 功能:截掉字符串左边的空格或指定字符。如果

rstrip()

​ 功能:删除字符串字符串末尾的空格.

strip([chars])

​ 功能:在字符串上执行 lstrip()和 rstrip()

lower()

​ 功能:转换字符串中所有大写字符为小写.

upper()

​ 功能:转换字符串中的小写字母为大写

swapcase()

​ 功能:将字符串中大写转换为小写,小写转换为大写

四:对齐

center(width, fillchar)

​ 功能:返回 一个指定的宽度 width 居中的字符串,fillchar 为填充的字符,默认为空格。

zfill (width)

​ 功能:返回 长度 为 width 的字符串,原字符串右对齐,前面填充 0

ljust(width[, fillchar])

​ 功能:返回 一个原字符串左对齐,并使用 fillchar 填充至长度 width 的新字符串,fillchar 默认为空格。

列表 list

定义

​ 由一系列变量组成的可变序列容器。

基础操作

1:创建列表:
列表名 = []
列表名 = list(可迭代对象)
2:添加元素:
列表名.append(元素)
列表.insert(索引,元素)
3:定位元素:
索引、切片
4:遍历列表:
正向:
for 变量名 in 列表名:
变量名就是元素
反向:
for 索引名 in range(len(列表名)-1,-1,-1):
列表名[索引名]就是元素
5:删除元素:
列表名.remove(元素)
del 列表名[索引或切片]

"""
列表:
适用性 : 存储多个数据
"""
# 1. 创建列表
# 空列表
list01 = []
list01 = list()
# 2. 增加
list02.append("小明")
# 插入 ( 索引 , 元素 )
list02.insert(3,"小红")
# 3. 删除
# 根据元素删除
list02.remove(4)
# 根据索引删除
del list02[3]
# 4. 修改
list02[0] = " 第一个元素 "
print(list02)
# 5. 切片 : 定位多个元素
# 获取 ( 重新创建新列表 )
# 前三个元素
list03 = list02[:3]
# 修改
# 修改后两个元素
list02[-2:] = [" 倒数第 2 个元素 ", " 倒数第 1 个元素 "]
print(list02)
# 通过切片定位 2 个元素,修改为 3 个元素
list02[2:4] = ["a","b","c"]
# 通过切片定位 3 个元素,修改为 0 个元素 [ 删除 ]
list02[2:5] = []
print(list02)
# 6. 查询
# 获取所有元素
for item in list02:
print(item)
# 倒序获取所有
# 不建议通过切片 ( 因为重新创建新列表 , 索引不建议 .)
# for item in list02[::-1]:
	# print(item)
# 建议通过索引
#2 1 0
# for i in range(2,-1,-1):
for i in range(len(list02)-1, -1, -1):
	print(list02[i])

#将列表中所有奇数删除,倒序删除
list1 = [1,5,16,90,9,10,3,6,44,79,11,7]
for i in range(len(list1)-1,-1,-1): 
    if list1[i] %2 != 0:          
        del list1[i]                #删除奇数元素.
print(list1)
深拷贝和浅拷贝

​ 浅拷贝:复制过程中,只复制一层变量,不会复制深层变量绑定的对象的复制过程。
​ 深拷贝:复制整个依懒的变量。

列表 VS 字符串

1:列表和字符串都是序列,元素之间有先后顺序关系。
2:字符串是不可变的序列,列表是可变的序列。
3:字符串中每个元素只能存储字符,而列表可以存储任意类型。
4: 列表和字符串都是可迭代对象。
5:函数:
将多个字符串拼接为一个。
result = “连接符”.join(列表)
将一个字符串拆分为多个。
列表 = “a-b-c-d”.split(“分隔符”)

# 将多个字符串拼接为一个 ,
#列表变字符串 .
list01 = ["a","b","c"]
str01 = "+".join(list01)# a+b+c
print(str01)
# 一个字符串拆分为多个 .
str01 = " 张无忌 _ 张翠山 _ 张三丰 "
list_result = str01.split("_")
print(list_result)
列表推导式

1:定义:
使用简易方法,将可迭代对象转换为列表。
2:语法:
变量 = [表达式 for 变量 in 可迭代对象]
变量 = [表达式 for 变量 in 可迭代对象 if 条件]
3:说明:
如果 if 真值表达式的布尔值为 False,则可迭代对象生成的数据将被丢弃。

list01 = [5,15,55,6,6,7]
list02 = []
for item in list01:
	list02.append(item + 1)
list03 = [item + 1 for item in list01]
# 列表推导式法
print(list02) # 结果 [6, 16, 56, 7, 7, 8]
print(list03) # 结果 [6, 16, 56, 7, 7, 8]
List01 = [5,15,55,6,6,7]
list02 = []
for item in list01:
	if item > 10:
		list02.append(item + 1)
list03 = [item + 1 for item in list01 if item > 10]
# 列表推导式
print(list02) # 结果 [16,56]
print(list03) # 结果 [16,56]
列表推导式嵌套

1:语法:
变量 = [表达式 for 变量 1 in 可迭代对象 1 for 变量 2 in 可迭代对象 2]

2:原理:

​ 外层循环做一次,内层循环做多次,外层循环控制行,内层循环控制列

3:传统写法:
result = []
for r in [“a”, “b”, “c”]:
for c in [“A”, “B”, “C”]:
result.append(r + c)
4:推导式写法:
result = [r + c for r in list01 for c in list02]

for r in range(2):# 0 1
	for c in range(3):#012 012
		print("*",end =" ")# 一行打印
	print()# 换行
	
# 结果   * * *
		* * *
    
for r in range(4):
#限定有多少行.
    for c in range(5):
#限定有多少列.
        if r % 2 ==0:
            print('*',end = '')
#限定偶数行为*
        else:
            print('#',end='')
    print()
    
# 结果   *****
		#####
        *****
        #####
        
for r in range(4):
# 限定有多少行.
    for c in range(r+1):
# 限定有多少列.
        print('*',end ='')
    print()
    
# 结果   *
		**
		***
		****
 
for r in range(1,10):
#限定有多少行.
    for c in range(1,10):
#限定有多少列.
        print('%d * %d = %d'%(r,c,r*c),end ='  ')
        if r == c:
            print()
            break

# 结果1 * 1 = 1  
	 2 * 1 = 2  2 * 2 = 4  
	 3 * 1 = 3  3 * 2 = 6  3 * 3 = 9  
	 4 * 1 = 4  4 * 2 = 8  4 * 3 = 12  4 * 4 = 16  
	 5 * 1 = 5  5 * 2 = 10  5 * 3 = 15  5 * 4 = 20  5 * 5 = 25  
	 6 * 1 = 6  6 * 2 = 12  6 * 3 = 18  6 * 4 = 24  6 * 5 = 30  6 * 6 = 36  
	 7 * 1 = 7  7 * 2 = 14  7 * 3 = 21  7 * 4 = 28  7 * 5 = 35  7 * 6 = 42  7 * 7 = 49  
	 8 * 1 = 8  8 * 2 = 16  8 * 3 = 24  8 * 4 = 32  8 * 5 = 40  8 * 6 = 48  8 * 7 = 56  8 * 8 = 64  
	 9 * 1 = 9  9 * 2 = 18  9 * 3 = 27  9 * 4 = 36  9 * 5 = 45  9 * 6 = 54  9 * 7 = 63  9 * 8 = 72  9 * 9 = 81 
        
list01 = [
    [1,2,3,4,5],
    [10,11,12,13,14],
    [20,21,22,23,24]
]
list02 = []
for c in range(len(list01[0])):
#获取list01的列数
    line = []
    for r in range(len(list01)):
        line.append(list01[r][c])
#获取list01每列的数据赋值给line[]
    list02.append(line)
#将line赋值给list02
print(list02)
#结果:[
	[1, 10, 20], 
    [2, 11, 21], 
    [3, 12, 22],
    [4, 13, 23], 
    [5, 14, 24]
    ]

list01 = ["a","b"]
list02 = ["A","B","C"]
list_result = []
#方法一:
for r in list01:
    for c in list02:
        list_result.append(r + c)
print(list_result)

#方法二:
list_result = [r + c for r in list01 for c in list02]
print(list_result)
#结果:['aA', 'aB', 'aC', 'bA', 'bB', 'bC']

列表list常用操作:

一:查找

L.index(v [, begin[, end]])

​ 功能:返回对应元素的索引下标, begin 为开始索引,end 为结束索引,当value 不存在时触发 ValueError 错误

L.count(x)

​ 功能: 用于统计某个元素在列表中出现的次数

L.pop([index])

​ 功能:删除索引对应的元素,如果不加索引,默认删除最后元素,同时返回删除元素的引用关系

二:修改

L.insert(index, obj)

​ 功能:将某个元素插放到列表中指定的位置

L.extend(lst)

​ 功能:向列表追加另一个列表

L.remove(x)

​ 功能:从列表中删除第一次出现在列表中的值

L.clear()

​ 功能:清空列表,等同于 L[:] = []

L.sort(reverse=False)

​ 功能:将列表中的元素进行排序,默认顺序按值 的小到大的顺序排列

L.reverse()

​ 功能:列表的反转,用来改变原列表的先后顺序

三:拷贝

L.copy()

​ 功能:复制此列表(只复制一层,不会复制深层对象)

元组 tuple

定义

​ 1:由一系列变量组成的不可变序列容器。
​ 2:不可变是指一但创建,不可以再添加/删除/修改元素。

基础操作

1:创建空元组:
元组名 = ()
元组名 = tuple()
2:创建非空元组:
元组名 = (20,)
元组名 = (1, 2, 3)
元组名 = 100,200,300
元组名 = tuple(可迭代对象)
3:获取元素:
索引、切片
4:遍历元组:
正向:
for 变量名 in 列表名:
变量名就是元素
反向:
for 索引名 in range(len(列表名)-1,-1,-1):
元祖名[索引名]就是元素

作用

1:元组与列表都可以存储一系列变量,由于列表会预留内存空间,所以可以增加元素。
2:元组会按需分配内存,所以如果变量数量固定,建议使用元组,因为占用空间更小。
3:应用:
变量交换的本质就是创建元组:x, y = (y, x)
格式化字符串的本质就是创建元祖:“姓名:%s, 年龄:%d” % (“tarena”, 15)

# 1. 空元组
tuple01 = ()
tuple01 = tuple()
# 2. 具有默认值元组
Tuple02 = (1,2)
# 3. 预留空间的存储机制即列表转换为按需分配的存储机制元组 :
list01 = ["a","b"]
tuple02 = tuple(list01)
print(tuple02) # 结果 (‘a’,‘b’)a’,‘a’,‘b’)b’)
#4. 按需分配的存储机制即元组转换为 预留空间的存储机制列表 :
list02 = list(tuple02)
print(list02) # 结果 [‘a’,‘b’)a’,‘a’,‘b’)b’]
#5. 特殊元组即只有一个元素的元组 :
tuple02 = ("a",) # 注意 : 如果元组只有一个元素,必须要在末尾添加逗号 .
print(tuple02)
#6. 多个变量 = 序列
name01,name02 = (" 无忌 "," 翠山 ")
print(name01) # 结果 无忌
print(name02) # 结果 翠山
tuple03 = ("a","b","c","d")
# 获取元素
# 单个元素
print(tuple03[2])
# 多个元素
print(tuple03[1:3])# ("b","c")
# 所有元素
# 正向
for item in tuple03:for i in range(4):
	print(item) 			print(tuple(i))
# 反向
for i in range(len(tuple03)-1,-1,-1):
	print(tuple03[i])

字典 dict

定义

1:由一系列键值对组成的可变散列容器。
2:散列:对键进行哈希运算,确定在内存中的存储位置,每条数据存储无先后顺序。
3: 键必须惟一且不可变(字符串/数字/元组),值没有限制。

基础操作

1:创建字典:
字典名 = {键 1:值 1,键 2:值 2}
字典名 = dict (可迭代对象)
2:添加/修改元素:
语法:
字典名[键] = 数据
说明:
键不存在,创建记录。键存在,修改映射关系。
3:获取元素:
变量 = 字典名[键] # 没有键则错误
4:遍历字典:
for 键名 in 字典名:
字典名[键名]
for 键名,值名 in 字典名.items():
语句
5:删除元素:
del 字典名[键]

1.# 创建空字典的字典 :
dict01 = {}
dict01 = dict()
2.# 创建具有默认值字典 :
dict02 = {"qtx":18,"ls":20,"ww":23}
list01 = [["a","b"],("c","d")]
dict02 = dict(list01)
print(dict02) # 结果 {'a': 'b', 'c': 'd'}
3.# 添加元素
# 第一次 ( 没有该键 ) 添加
dict02[" 键 "] = " 值 "
4.# 修改元素
dict02[" 键 "] = " 值 2"
dict02["a"] = "B"
print(dict02) # 结果 {'a': 'B', 'c': 'd', ' 键 ': ' 值 2'}
5.# 删除
del dict02[" 键 "]
print(dict02) # 结果 {'a': 'B', 'c': 'd'}
6.# 查找单个元素
# 在查找元素时 , 如果字典中不存在该键,则错误 .
# 所以查找前,一定通过 in 判断。
if "qtx" in dict02:
	print(dict02["qtx"])
else: #先查找 , 后才可判断是
	print(" 不存在 ")
7.# 获取所有元素
for key in dict02:
	print(key) # 结果为 ( 键 ) 即 a c
	print(dict02[key]) # 结果为 ( 值 ) 即 B d
8.# 获取 键 , 获取值
for item in dict02.items():
	print(item[0]) # 结果为 ( 键 ) 即 a c
	print(item[1]) # 结果为 ( 值 ) 即 B d
9.# 获取 键 , 获取值
for key,value in dict02.items():
	print(key) # 结果为 ( 键 ) 即 a c
	print(value) # 结果为 ( 值 ) 即 B d
10.# 获取字典中所有值
for value in dict02.values():
	print(value) # 结果为 ( 值 ) 即 B d
字典推导式

1:定义:
使用简易方法,将可迭代对象转换为字典。
2:语法:
{键:值 for 变量 in 可迭代对象}
{键:值 for 变量 in 可迭代对象 if 条件}

#字典推导式的运用 :
dict01 = {}
for item in range(10):
	dict01[item] = item ** 2
dict02 = {item: item ** 2 for item in range(10)}
print(dict01) # 结果是{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
print(dict02) # 结果是{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
dict01 = {}
for item in range(10):
	if item > 5:
		dict01[item] = item ** 2
dict02 = {item: item ** 2 for item in range(10) if item > 5}
print(dict01) # 结果是 {6: 36, 7: 49, 8: 64, 9: 81}
print(dict02) # 结果是 {6: 36, 7: 49, 8: 64, 9: 81}
字典 VS 列表

1: 都是可变容器。
2:获取元素方式不同,列表用索引,字典用键。
3:字典的插入,删除,修改的速度快于列表。
4:列表的存储是有序的,字典的存储是无序的。

总结:存储多个数据,使用什么数据结构?

根据具体需求,结合优缺点,综合考虑( 两害相权其轻 )
字典:
优:根据 key 获取 value ,速度最快 .如果信息较多,通过键 ( 指定的名称 ) 获取 ,代码可读性偏好。
缺 : 不能通过索引 / 切片获取元素,不灵活 ,内存占用较大
列表:
优:能通过索引 / 切片获取元素,灵活 .
缺 : 数据过多时,查找元素较慢 ,通过索引 ( 整数 ) 获取,如果信息较多,代码可读性偏差。

''''
    录入人的信息(姓名,年龄,性别,体重)
    1.如果名称为空字符,则停止录入
    2.将所有人的信息打印出来(一人一行)
    数据结构:字典内嵌套列表{'无忌':[28,'男',88]
'''''
dict_person_info = {}
#循环外创建个人信息原始空字典
while True:
    name = input('请输入姓名')
    if name =='':
        break
    age = int(input('请输入年龄'))
    sex = input('请输入性别')
    weight = float(input('请输入体重'))
    dict_person_info [name] = [age,sex,weight]
#将个人姓名及其个人信息添加到个人信息原始空列表中.
    print(dict_person_info)
for k_name,v_info in dict_person_info.items():
#遍历字典,获取字典中个人姓名及其个人信息.
    print('%s的年龄是%d,性别%s,体重%f:'% (k_name, v_info[0], v_info[1], v_info[2]))

#结果:{'无忌':[28,'男',88]
	 #无忌的年龄是28,性别男,体重88.000000:

字典dict常用操作:

一:查找

get(key, default=None)
功能:返回指定键的值,如果值不在字典中返回 default 值
setdefault(key, default=None)
功能:和 get()类似, 但如果键不存在于字典中,将会添加键并将值设为 default
popitem()
功能:随机返回并删除字典中的一对键和值(一般删除末尾对)。
items()
功能:以列表返回可遍历的(键, 值) 元组数组
keys()
功能:返回一个迭代器,可以使用 list() 来转换为列表
values()
功能:返回一个迭代器,可以使用 list() 来转换为列表

二:修改

update(dict2)
功能:字典记录累加
clear()
功能:删除字典内所有元素

集合 set:功能 : 将其他具有重复元素的容器转换为集合 ( 去重复 )

定义

​ 1: 由一系列不重复的不可变类型变量(元组,字符串,)组成的可变散列容器。
​ 2:相当于只有键没有值的字典(键则是集合的数据)。

基础操作

1:创建空集合:
集合名 = set()
集合名 = set(可迭代对象)
2:创建具有默认值集合:
集合名 = {1, 2, 3}
集合名 = set(可迭代对象)
3:添加元素:
集合名.add(元素)
4:删除元素:
集合名.discard(元素)

# 创建空集合
s01 = set()
print(type(s01)) # 结果 :class 'set'
# 创建具有默认值的集合
s02 = {"a","b"}
s02 = set("abcabc")
print(s02) # 结果 {'a', 'c', 'b'} 去除了重复数 abc
# 增加
s02.add("qtx")
s02.add("mly")
print(s02) # 结果 {'b', 'c', 'qtx', 'a', 'mly'}因为集合是可变散列
# 删除
s02.remove("mly")# 如果没有该元素 则报错
print(s02) # 结果 {'a', 'c', 'b', 'qtx'}
# 获取所有
for item in s02:
	print(item)
运算

1:交集&:返回共同元素。
s1 = {1, 2, 3}
s2 = {2, 3, 4}
s3 = s1 & s2 # {2, 3}
2:并集:返回不重复元素
s1 = {1, 2, 3}
s2 = {2, 3, 4}
s3 = s1 | s2 # {1, 2, 3, 4}
3:补集-:返回只属于其中之一的元素
s1 = {1, 2, 3}
s2 = {2, 3, 4}
s1 - s2 # {1} 属于 s1 但不属于 s2
补集^:返回不同的的元素
s1 = {1, 2, 3}
s2 = {2, 3, 4}
s3 = s1 ^ s2 # {1, 4} 等同于(s1-s2 | s2-s1)
4:子集<:判断一个集合的所有元素是否完全在另一个集合中

5:超集>:判断一个集合是否具有另一个集合的所有元素
s1 = {1, 2, 3}
s2 = {2, 3}
s2 < s1 # True
s1 > s2 # True
6:相同或不同== !=:判断集合中的所有元素是否和另一个集合相同。
s1 = {1, 2, 3}
s2 = {3, 2, 1}
s1 == s2 # True
s1 != s2 # False
子集或相同,超集或相同 <= >=

集合推导式

1:定义:
使用简易方法,将可迭代对象转换为集合。
2:语法:
{表达式 for 变量 in 可迭代对象}
{表达式 for 变量 in 可迭代对象 if 条件}

集合set常用操作:

update()

​ 功能:给集合添加元素
clear()

​ 功能:移除集合中的所有元素
copy()

​ 功能:拷贝一个集合
pop()

​ 功能:随机移除元素

固定集合 frozenset:

​ 主要作用:与其他容器互相转换;次要作用 : 可以作为字典的 key

定义

​ 不可变的集合。

作用

​ 固定集合可以作为字典的键,还可以作为集合的值。

基础操作

​ 创建固定集合:frozenset(可迭代对象)

运算

​ 等同于 set

函数 function

pycharm 相关设置

1:“代码自动完成”时间延时设置:

​ file -> settings -> editor -> general -> code completion -> autopopup in (ms):0

2:快捷键:

ctrl + P参数信息(在方法中调用参数)
ctrl + q快速查看文档
ctrl + alt + m提取方法

定义

1:用于封装一个特定的功能,表示一个功能或者行为。
2:函数是可以重复执行的语句块, 可以重复调用。

作用

提高代码的可重用性和可维护性(代码层次结构更清晰)。

定义函数

1:语法:
def 函数名(形式参数):
函数体
2: 说明:
def 关键字:全称是 define,意为”定义”。
函数名:对函数体中语句的描述,规则与变量名相同。
形式参数:方法定义者要求调用者提供的信息。
函数体:完成该功能的语句。
3:函数的第一行语句建议使用文档字符串描述函数的功能与参数。

调用函数

1:语法:函数名(实际参数)
2:说明:根据形参传递内容。

返回值

1:定义:
方法定义者告诉调用者的结果即做函数的人,给用函数的人的结果return 返回结果 退出方法
2:语法:
return 数据
3:说明:
return 后没有语句,相当于返回 None。
函数体没有 return,相当于返回 None。

def add(a, b):
    print('计算两个数的和:{0},{1},{2}'.format(a, b, (a + b)))
    return a + b


def test01():
    print('liu')
    print('li')
    return
    #两功能:1.返回值,2‘结束函数执行
    print('hello')


c = add(30, 40) #结果:计算两个数的和:30,40,70
print(add(30, 40) * 10)
#结果:计算两个数的和:30,40,70
		700
d = test01()
print(d)
#结果:liu
	  li
	  None

可变/不可变类型在传参时的区别

1:不可变类型参数有:
数值型(整数,浮点数,复数)
布尔值 bool
None 空值
字符串 str
元组 tuple
固定集合 frozenset
2:可变类型参数有:
列表 list
字典 dict
集合 set
3:传参说明:
不可变类型的数据传参时,函数内部不会改变原数据的值。
可变类型的数据传参时,函数内部可以改变原数据。

函数参数:函数调用者传递给函数定义者的信息

实参传递方式 argument
位置传参

​ 定义:实参与形参的位置依次对应。

序列传参

​ 定义:实参用*将序列拆解后与形参的位置依次对应。

关键字传参

​ 定义:实参根据形参的名字进行对应。

字典关键字传参

1:定义:实参用**将字典拆解后与形参的名字进行对应。
2:作用:配合形参的缺省参数,可以使调用者随意传参。

#实际参数
def fun01(a, b, c):
	print(a)
	print(b)
	print(c)
# 1. 位置实参 : 实参根据位置与形参进行对应
fun01(1, 2, 3) #调用函数产生结果: 1
								2
    							3

def print_rectangle(r_count,c_count,char):
    for r in range(r_count):
#定义行数
        for c in range(c_count):
#定义列数
            print(char,end=' ')
#定义图形
        print()
#换行作用
print_rectangle(5,3,'*#')
#调用函数产生结果: *# *# *# 
				 *# *# *# 
				 *# *# *# 
				 *# *# *# 
				 *# *# *# 

#定义矩阵转置函数
def exchange_list(list_target):
    list02 = []
    for c in range(len(list_target[0])):
        list02.append([])
        for r in range(len(list_target)):
            list02[c].append(list_target[r][c])
    return list02
list01 = [
    [1,2,3,4],
    [11,12,13,14],
    [21,22,23,24]
]
re = exchange_list(list01)
print(re)
#结果:[[1, 11, 21], [2, 12, 22], [3, 13, 23], [4, 14, 24]]

#定义方阵转置函数
def square_matrix_transpose(list_matrix):
    for c in range(1, len(list_matrix)):  # 1 2 3
        for r in range(c, len(list_matrix)):
            list_matrix[r][c - 1], list_matrix[c - 1][r] = list_matrix[c - 1][r], list_matrix[r][c - 1]

list01 = [
    [1, 2, 3],
    [11, 12, 13],
    [21, 22, 23],
]
square_matrix_transpose(list01)  # 转置1
print(list01)
#结果:[[1, 11, 21], [2, 12, 22], [3, 13, 23]]
square_matrix_transpose(list01)  # 转置2
print(list01) 
#结果:[[1, 2, 3], [11, 12, 13], [21, 22, 23]]

#定义将列表依据升系列排布.
def sort(list_target):
    # 获取需要与后面比较的数据(除去最后一个)list_target[r]
    for r in range(len(list_target)-1):
        # 与后面 list_target[c] 元素进行比较
        for c in range(r+1,len(list_target)):
            if list_target[r] > list_target[c]:
                list_target[r],list_target[c] = list_target[c],list_target[r]
list01 = [13,5,15,6,7]
sort(list01)
print(list01)#结果:[5, 6, 7, 13, 15]
                
# 2. 序列实参 : 使用星号将序列中的元素拆开,与形参进行对应 .
# 序列 : 字符串 列表 元组
list01 = ["aaa", "bb", "cc"]
fun01(*list01) #调用函数产生结果: aaa
								bbb
    							ccc
# 3. 关键字实参:实参根据名称与形参进行一一对应
fun01(b=2, a=1, c=3) #调用函数产生结果: 1
									  2
    								  3
# 4. 字典实参:使用双星号将字典中的元素拆开 , 根据键形参进行一一对应 , 传递值
dict01 = {"c": 33, "a": 11, "b": 22}
fun01(**dict01) #调用函数产生结果: 11
							     22
    						     33
形参定义方式 parameter
缺省参数即默认形参:实参可以不传递数据。

1: 语法:
def 函数名(形参名 1=默认实参 1, 形参名 2=默认实参 2, …):
函数体
2:说明:
缺省参数必须自右至左依次存在,如果一个参数有缺省参数,则其右侧的所有参数都必须有缺省参数。
缺省参数可以有 0 个或多个,甚至全部都有缺省参数。

位置形参:实参根据位置进行对应

语法:
def 函数名(形参名 1, 形参名 2, …):
函数体

星号元组形参:实参数量无限(将实参合并为元组)

1:语法:
def 函数名(*元组形参名):
函数体
2:作用:
收集多余的位置传参。
3:说明:
一般命名为’args’
形参列表中最多只能有一个

命名关键字形参:实参必须是关键字实参

1:语法:
def 函数名(*, 命名关键字形参 1, 命名关键字形参 2, …):
函数体
def 函数名(*args, 命名关键字形参 1, 命名关键字形参 2, …):
函数体
2:作用:
强制实参使用关键字传参

双星号字典形参:实参数量无限(将实参合并为字典)

1:语法:
def 函数名(**字典形参名):
函数体
2:作用:
收集多余的关键字传参
3:说明:
一般命名为’kwargs’
形参列表中最多只能有一个

参数自左至右的顺序

​ 位置形参 --> 星号元组形参 --> 命名关键字形参 --> 双星号字典形参

''''
    函数的形参
'''''
#1.默认参数:实参可以不传递数据(从右往左依次存在)
def fun01(a=6,b=5,c=4):
    print(a)
    print(b)
    print(c)
fun01() #调用函数产生结果: 6
						 5
    					 4
fun01(1) #调用函数产生结果: 1
						  5
    					  4
fun01(1,'d') #调用函数产生结果: 1
						  	  d
    					      4

#2.关键实参+默认形参:调用者可以随意
fun01(b='dddd') #调用函数产生结果: 6
						  		 dddd
    					  		 4
#3.星号元组形参,让位置实参的位置无限
def fun02(p1,p2,*args):
    print(args)
fun02(1,2) #调用函数产生结果: ()
fun02(1,2,3) #调用函数产生结果: (3,)
fun02(1,2,3,4,5) #调用函数产生结果: (3,4,5)

#4.命名关键字形参,传递的实参必须是关键字实参,
# 写法1:星号元组形参以后的参数是命名关键字形参
def fun03(*args,p1='',p2):
    print(args)
    print(p1)
    print(p2)
fun03(2,2,p1=11,p2=22) #调用函数产生结果: (2,2)
						  		 		11
    					  		 		22
fun03(p1=11,p2=22) #调用函数产生结果: ()
						  		 	11
    					  		 	22
fun03(p2=6) #调用函数产生结果: ()
						  	
    					  	 6

# 写法2:星号以后的位置形参是命名关键字形参
def fun04(*, p1=0, p2):
    print(p1, p2)
fun04(p1=1, p2=2) #调用函数产生结果:1 2
fun04(p2=2) #调用函数产生结果:0 2

#5双星号字典形参:让关键字实参的数量无限
def fun05(**kwargs):
    print(kwargs)
fun05(a=1,b=8,c=10) #调用函数产生结果:{'a': 1, 'b': 8, 'c': 10}
fun05(a=1, b=2) #调用函数产生结果:{'a': 1, 'b': 2}
fun05(a=1) #调用函数产生结果:{'a': 1}

def fun06(a,*args,c,d='dd',**kwargs):
    print(a)
    print(args)
    print(c)
    print(d)
    print(kwargs)
fun06(1,5,7,6,c=8) #调用函数产生结果:1
								   (5, 7, 6)
								   8
								   dd
								   {}

def fun07(*args,**kwargs):
    print(args)
    print(kwargs)
fun07(56,70,60,a=110) #调用函数产生结果:(56, 70, 60)
									  {'a': 110}

在这里插入图片描述

作用域 LEGB

​ 1:作用域:变量起作用的范围。
​ 2:Local 局部作用域:函数内部。
​ 3:Enclosing 外部嵌套作用域 :函数嵌套。
​ 4:Global 全局作用域:模块(.py 文件)内部。
​ 5:Builtin 内置模块作用域:builtins.py 文件。

变量名的查找规则

1: 由内到外:L -> E -> G -> B
2:在访问变量时,先查找本地变量,然后是包裹此函数外部的函数内部的变量,之后是全局变量,
最后是内置变量。

局部变量

1:定义在函数内部的变量(形参也是局部变量)
2:只能在函数内部使用
3:调用函数时才被创建,函数结束后自动销毁

全局变量

1:定义在函数外部,模块内部的变量。
2:在整个模块(py 文件)范围内访问(但函数内不能将其直接赋值)。

global 语句

1:作用:
在函数内部修改全局变量。
在函数内部定义全局变量(全局声明)。
2:语法:
global 变量 1, 变量 2, …
3:说明
在函数内直接为全局变量赋值,视为创建新的局部变量。
不能先声明局部的变量,再用 global 声明为全局变量。

nonlocal 语句

1:作用:
在内层函数修改外层嵌套函数内的变量
2:语法
nonlocal 变量名 1,变量名 2, …
3:说明
在被嵌套的内函数中进行使用

# 全局变量
g01 = "悟空"
g02 = "八戒"
g03 = "沙僧"

def fun01():
    l01 = 100
    print(l01)# 只能在函数内部使用局部变量:100

    print(g01)# 在函数内部可以访问全局变量:悟空

    # 创建了局部变量g02,覆盖了全局变量g02
    g02 = "老朱"
    print("fun01---"+g02)# fun01---老朱

    # 声明全局变量g03
    global g03
    g03 = "老沙"

fun01()
print("全局---"+g02)# 全局---八戒
print(g03) # 老沙
dict_commodity_info = {
    101: {"name": "小米", "price": 50},
    102: {"name": "大豆", "price": 60},
    103: {"name": "花生油", "price": 70},
    104: {"name": "糖果", "price": 30},
    105: {"name": "鸡肉", "price": 40},
    106: {"name": "苹果", "price": 10}
}

list_order = []
#创建订单列表
def shopping():
    """
        购物
    :return:
    """
    while True:
        item = input("1键购买,2键结算。")
        if item == '1':
            buying()
        elif item == '2':
            settlement()
def buying():
    """
        购买
    :return:
    """
    print_commodity_info()
    create_order()
    print('添加到购物车。')
def create_order():
    """
        创建订单
    :return:
    """
    while True:
        cid = int(input("请输入商品编号:"))
        if cid in dict_commodity_info:
            break
        else:
            print("该商品不存在")
    count = int(input("请输入购买数量:"))
    dict_single_order = {'cid':cid,'count':count}
#创建一条订单
    list_order.append(dict_single_order)
#添加到订单列表中
def print_commodity_info():
    """
        打印商品信息
    """
    for key, value in dict_commodity_info.items():
        print("编号:%d,名称:%s,单价:%d。" % (key, value["name"], value["price"]))
def settlement():
    """
        结算
    """
    print_orders_info()
    total_price = get_total_price()
    paying(total_price)
def paying(total_price):
    """
        支付
    :param total_price: 需要支付的价格
    """
    while True:
        money = float(input("总价%d元,请输入金额:" % total_price))
        if money >= total_price:
            print("购买成功,找回:%d元。" % (money - total_price))
            list_order.clear()
            break
        else:
            print("金额不足.")
def get_total_price():
    """
        获取总价格
    """
    total_price = 0
    for item in list_order:
        commodity = dict_commodity_info[item["cid"]]
        total_price += commodity["price"] * item["count"]
    return total_price
def print_orders_info():
    """
        打印所有订单信息
    """
    for item in list_order:
        commodity = dict_commodity_info[item["cid"]]
        print("商品:%s,单价:%d,数量:%d." % (commodity["name"], commodity["price"], item["count"]))
shopping()

面向对象 Object Oriented

概述

面向过程:做事

1.分析出解决问题的步骤,然后逐步实现。
例如:婚礼筹办
– 发请柬(选照片、措词、制作)
– 宴席(场地、找厨师、准备桌椅餐具、计划菜品、购买食材)
– 婚礼仪式(定婚礼仪式流程、请主持人)

2.公式: 程序 = 算法 + 数据结构

3.优点:所有环节、细节自己掌控。

4.缺点:考虑所有细节,工作量大。

面向对象:找

1.找出解决问题的人,然后分配职责。
例如:婚礼筹办
– 发请柬:找摄影公司(拍照片、制作请柬)
– 宴席:找酒店(告诉对方标准、数量、挑选菜品)
– 婚礼仪式:找婚庆公司(对方提供司仪、制定流程、提供设备、帮助执行)
2.公式: 程序 = 对象 + 交互
3.优点
(1)思想层面:
– 可模拟现实情景,更接近于人类思维。
– 有利于梳理归纳、分析解决问题。
(2)技术层面:
– 高复用:对重复的代码进行封装,提高开发效率。
– 高扩展:增加新的功能,不修改以前的代码。
– 高维护:代码可读性好,逻辑清晰,结构规整。
4.缺点:学习曲线陡峭。

class Student:
    def __init__(self,name,sex,score,age):
#创建构造函数,每个学生的信息各不同
        self.name = name
        self.sex = sex
        self.score =score
        self.age = age
    def print_self(self):
#创建打印的实例类方法,打印每个人的所有信息.
        print(self.name,self.sex,self.score,self.age)
list01 = [
    Student('小红','女',86,28),
    Student('小明','男',99,26),
    Student('小李','女',76,25),
    Student('小刘','男',70,21)
]

def find01():
#定义在列表1中找到'小明'同学的函数1
    for item in list01:
        if item.name =='小明':
            return item
#因为设计要求是找到小明,所有要返回小明的值,所有要return.
student01 = find01()
#调用函数1
if student01:
# 如果函数没有找到,则错误.所以如果不能确定是否找到,需要判断.
    print(student01.name)
#结果:单一只打印小明的名字:#小明

def find02():
#定义在列表1中找到所有女同学的函数2
    list02 = []
#定义空列表,因为女同学可能不止一个.
    for item in list01:
        if item.sex =='女':
            list02.append(item)
    return list02
#因为设计要求是找到所有女同学,所有要返回列表2的值,所有要return.
list02 = find02()
#调用函数2
for item in list02:
    item.print_self()
#用实例调用打印的实例类方法,打印每个学生所有信息
##结果:#小红 女 86 28
        #小李 女 76 25

def find03():
#定义在列表1中查找所有同学姓名的函数3.
    list03 = []
#定义空列表存每个同学名字,因为同学可能很多.
    for item in list01:
        list03.append(item.name)
    return list03
#因为设计要求是找到所有同学的名字,所有要返回列表3的值,所有要return.
list03 = find03()
#调用函数3
for item in list03:
    print(item)
#单一打印每个同学的名字,不需要所有信息
##结果:小红
        #小明
        #小李
        #小刘

def find04():
#定义将列表1中所有女同学的成绩加10分的函数4.
    for item in list01:
        if item.sex =='女':
            item.score +=10
find04()
#调用函数4
for item in list01:
    item.print_self()
#用实例调用打印的实例类方法,打印每个同学所有信息
##结果:小红 女 96 28
      #小明 男 99 26
      #小李 女 86 25
      #小刘 男 70 21

def del01():
#定义将列表1中所有不到80分的学生删除的函数5.
    for i in range(len(list01)-1,-1,-1):
#从后向前删除对象
        if list01[i].score < 80:
            del list01[i]
del01()
#调用函数5
for item in list01:
    item.print_self()
#用实例调用打印的实例类方法,打印每个同学所有信息
##结果:小红 女 86 28
      #小明 男 99 26

类和对象

1.类 :一个抽象的概念,即生活中的“类别”
2.对象 :类的具体实例,即归属于某个类别的”个体”。

3.类是创建对象 的 模板”。
– 数据成员:名词类型的状态。
– 方法 成员:动词类型的行为。
4.类与类行为不同,对象 与对象 数据不同。

语法
定义类

1.代码

class 类名:
	””” 文档说明”””
	def _init_(self,参数列表):
		self. 实例变量 = 参数
	方法 成员

2.说明
– 类名所有单词首字母大写.
init 也叫构造函数,创建对象 时被调用,也可以省略。
– self 变量绑定的是被创建的对象 ,名称可以随意。

class Wife:
	# 构造函数
	def __init__(self,name,height,weight):
		self.height = height
		self.weight = weight
		self.name = name
	# 行为
	def play(self):
		# 方法 可以访问数据
		print(self.name + "在玩耍 ")
# 创建对象
# 类名 (参数 ...) 调用 __init__方法
w01 = Wife("翠花 ",1.8,180)
w01.play()# 通过对象 地址调用方法 ,会自动传递对象 地址 . #结果 :翠花在玩耍
w02 = Wife("如花 ",2.1,20)
w02.play() #结果 :如花在玩耍
# 同一个方法 ,可以访问不同的对象 数据(方法中self指向了不同对象 ).
创建对象 (实例化)

变量 = 构造函数 (参数列表)

实例成员

实例成员 :对象 自己的成员 (数据 /行为 )
类成员 :大家共享的成员

实例变量

1.语法
(1)定义:对象 .变量名
(2)调用:对象 . 变量名
2.说明
(1)首次通过对象 赋值为创建,再次赋值为修改.
w01 = Wife()
w01.name = “ ” 丽丽
w01.name = “ ” 莉莉
(2)通常在构造函数(init)中创建。
w01 = Wife(“ ” 丽丽 ,24)
print(w01.name)
(3)每个对象 存储一份,通过对象 地址访问。
3.作用:描述某个对象 的数据 。
4.dict:对象 的属性,用于存储自身实例变量的字典。

class Wife:
	def __init__(self, name, height):
        # 构造函数 init:将数据传递给创建的对象 .
		self.name = name
		self.height = height
	def print_self(self):
		print(self.name, self.height)
w01 = Wife("翠花 ", 2.1) # 调用了构造函数 init
# 将老婆对象 地址赋值给 w02(两个变量指向同一个老婆对象 )
w02 = w01
# 通过其中一个变量修改老婆姓名
w01.name = "翠翠 "
# 通过另外一个变量访问老婆信息
w02.print_self() # "翠翠 " 2.1
list01 = [w01, w02, Wife("如花 ", 1.8)]
list02 = list01
list01[2].height = 1.9
list02[2].print_self()# 如花 1.9
实例方法

1.语法
(1) 定义: def 方法 名称(self, 参数列表):
方法 体
(2) 调用: 对象 地址.实例方法 名(参数列表)不建议通过类名访问实例方法
2.说明
(1) 至少有一个形参,第一个参数绑定调用这个方法的对象 ,一般命名为"self"。
(2) 无论创建多少对象 ,方法 只有一份,并且被所有对
象 共享。
3.作用:表示对象 行为。

类成员 :大家共享的成员
类变量

1.语法
(1)定义:在类中,方法 外定义变量。
class 类名:
变量名 = 表达式
(2)调用:类名.变量名
不建议通过对象 访问类变量
2.说明
(1) 存储在类中。
(2) 只有一份,被所有对象 共享。
3.作用:描述所有对象 的共有数据。

类方法

1.语法
(1)定义:
@classmethod
def 方法 名称(cls,参数列表):
方法 体
(2)调用:类名 . 方法 名 ( 参数列表 )不建议通过对象 访问类方法
2.说明
(1) 至少有一个形参,第一个形参用于绑定类,一般命名为’cls’ cls’cls’
(2) 使用@classmethod修饰的目的是调用类方法 时可以隐式传递类。
(3) 类方法 中不能访问实例成员,实例方法 中可以访问类成员。
3.作用:操作类变量。

class ICBC:
	# 类变量 :总行的钱
	total_money = 1000000
	# 类方法
	@classmethod
	def print_total_money(cls):
		print(id(cls), id(ICBC))#地址相同
		# cls : 存储当前类的地址
		# print("当前总行金额 :",ICBC.total_money)
		print("当前总行金额 :",cls.total_money)
	def __init__(self, name, money):
		self.name = name
		self.money = money
		# 从总行扣除当前支行的钱
		ICBC.total_money -= money
i01 = ICBC("天坛支行 ", 100000)
i02 = ICBC("陶然亭支行 ", 100000)
# 主流 :通过类访问类成员
ICBC.print_total_money()#800000
print(ICBC.total_money)#800000
# 非主流 :通过对象 访问类成员
# print(i02.total_money)
# i02.print_total_money()
静态方法

1.语法
(1)定义:
@staticmethod
def 方法 名称(参数列表):
方法 体
(2)调用:类名.方法 名(参数列表)
不建议通过对象 访问静态方法
2.说明
(1) 使用@ staticmethod修饰的目的是该方法 不需要隐式传参数。
(2) 静态方法 不能访问实例成员和类成员
3.作用:定义常用的工具函数。

三大特征 : 封装 , 继承 , 多态 .

封装:把数据和行为一起封装起来.

数据角度讲:将多个变量包装为一个对象 .

1.定义:
将一些基本数据类型复合成一个自定义类型。
2.优势:
将数据与对数据的操作相关联。
代码可读性更高(类是对象 的模板”。)。

行为角度讲

1.定义:
向类外提供必要的功能,隐藏实现的细节。
2.优势:
简化编程,使用者不必了解具体的实现细节,只需要调用对外提供的功能。
3.私有成员:
(1)作用:无需向类外提供的成员,可以通过私有化进行屏蔽。
(2)做法 :命名使用双下划线开头。
(3)本质:障眼法 ,实际也可以访问。
私有成员的名称被修改为:_ 类名 __ 成员名 ,可以通过_dict_属性或 dir函数查看。
4.属性@property:
公开的实例变量,缺少逻辑验证。私有的实例变量与两个公开的方法 相结合,又使调用者的操作略显复杂。而属性可以将两个方法 的使用方式像操作变量一样方便。
(1)定义:

@property
def 属性名(self):
	return self.__属性名
@属性名.setter
def 属性名(self, value):
	self.__属性名= value

​ (2)调用:
​ 对象 . 属性名 = 数据
​ 变量 = 对象 .属性名
​ (3)说明:
​ 通常两个公开的属性,保护一个私有的变量。
​ @property 负责读取,@属性名.setter 负责写入
​ 只写:属性名= property(None, 写入方法 名)

class Skill:
	def __init__(self,name,attack,time,total):
		self.name = name
		self.attack = attack
		self.time = time
		self.total = total
	@property
	def attack(self):
		return self.__attack
	@attack.setter
	def attack(self, value1):
		if 0.1 <= value1 <= 5:
			self.__attack = value1
		else:
			raise ValueError('cls' 错误 'cls' )
	@property
	def time(self):
		return self.__time
	@time.setter
	def time(self, value2):
		if 0.1 <= value2 <= 10:
			self.__time = value2
		else:
			raise ValueError('cls' 错误 'cls' )
	@property
	def total(self):
		return self.__total
	@total.setter
	def total(self, value3):
		if 0 <= value3 <= 100:
			self.__total = value3
		else:
			raise ValueError('cls' 错误 'cls' )
sk1 = Skill('cls' 金刚 'cls' ,4,5,60)
print(sk1.attack)#4
print(sk1.time)#5
print(sk1.total)#60
设计角度讲:拿到项目 ,先想主体框架 ,后细分 ,定代码 .

1.定义:
(1) 分而治之
将一个大的需求分解为许多类,每个类处理一个独立的功能。
(2) 变则疏之
变化的地方独立封装,避免影响其他类。
(3) 高 内 聚
类中各个方法 都在完成一项任务(单一职责的类) 。
(4) 低 耦 合 耦 合 合
类与类的关联性与依赖度要低 耦 合(每个类独立),让一个类的改变,尽少影响其他类。
2.优势:
便于分工,便于复用,可扩展性强。

案例:信息管理系统

在这里插入图片描述

需求

​ 实现对学生信息的增加、删除、修改和查询。

分析

​ 界面可能使用控制台,也可能使用 Web等等。
1.识别对象 : 界面视图类 逻辑控制类 数据模型类
2.分配职责:
​ 界面视图类:负责处理界面逻辑,比如显示菜单,获取输入,显示结果等。
​ 逻辑控制类:负责存储学生信息,处理业务逻辑。比如添加、删除等
​ 数据模型类:定义需要处理的数据类型。比如学生信息。
3.建立交互:
​ 界面视图对象 <----> 数据模型对象 <----> 逻辑控制对象

面对对象编程思维架构:封装设计思维 :创建三个类

模型 Model:负责封装数据
控制 Controller:负责逻辑处理
视图 View:负责界面逻辑
(1)需求 :比如添加学生
(2)识别”。对象 :找谁干活
(3)建立交互 :互相调用
“我在哪 ,他在哪 ?”

在这里插入图片描述

在这里插入图片描述

设计
数据模型类:StudentModel
	数据: 编号 id , 姓名 name, 年龄 age, 成绩 score
逻辑控制类:StudentManagerController
	数据:学生列表 __stu_list #代表私有化 ,只读
	行为:获取列表 stu_list, 添加学生 add_student,删除学生 remove_student,修改学生update_student,根据成绩 排序 order_by_score。
	界面视图类:StudentManagerView
		数据:逻辑控制对象 __manager
		行为:显示菜单__display_menu,选择菜单项__select_menu_item,
     入口逻辑:main,
		输入学生 __input_students,输出学__output_students, 删除学生__delete_student,修改学生信息__modify_student
继承
语法 角度讲
继承方法

1.代码:
class 父类:
def 父类方法 (self):
方法 体
class 子类(父类):
def 子类方法 (self):
方法 体
儿子 = 子类()
儿子.子类方法 ()
儿子.父类方法 ()
2.说明:
子类直接拥有父类的方法 .

内置函数

​ isinstance(对象 , 类型)
​ 返回指定对象 是否是某个类的对象 。
​ issubclass(类型,类型)
​ 返回指定类型是否属于某个类型。

继承数据

1.代码

class 子类(父类):
	def __init__(self,参数列表):
		super().__init__(参数列表)
		self. 自身实例变量 = 参数

2.说明
子类如果没有构造函数,将自动执行父类的,但如果有构造函数将覆盖父类的。此时必须通过super()函数调用父类的构造函数,以确保父类实例变量被正常创建。
定义
重用现有类的功能,并在此基础上进行扩展。
说明:子类直接具有父类的成员(共性),还可以扩展新功能。
优点
一种代码复用的方式。
缺点
耦 合合度高:父类的变化,直接影响子类。

class Person:
	def __init__(self, name=""):
		self.name = name
class Student(Person):
	def __init__(self, name="", score=0):
		self.score = score
		# self.name = name
		# 如果子类没有构造函数 ,使用父类构造函数
		# 如果子类有构造函数 ,必须铜通过 super()调用父类构造函数 ,否则会覆盖父类 (不执行 )的 .
		super().__init__(name)
# 创建实例变量
s01 = Student("无忌 ", 100)
print(s01.name) #结果 :无忌
print(s01.score) #结果 :100
p01 = Person("翠山 ")
print(p01.name) #结果 :翠山
设计角度讲
定义

​ 将相关类的共性进行抽象 ,统一概念,隔离变化。

适用性

​ 多个类在概念上是一致的,且需要进行统一的处理。

相关概念

​ 父类(基类、超类)、子类(派生类)。
​ 父类相对于子类更抽象 ,范围更宽泛;子类相对于父类更具体,范围更狭小。
​ 单继承:父类只有一个(例如 Java,C#)。
​ 多继承:父类有多个(例如C++,Python)。
​ Object 类:任何类都直接或间接继承自 object 类。

多继承

​ 一个子类继承两个或两个以上的基类,父类中的属性和方法 同时被子类继承下来。
​ 同名方法 的解析顺序 (MRO , Method Resolution Order):
​ 类自身 --> 父类继承列表(由左至右)–> 再上层父类
A
/
/
B C
\ /
\ /
D

多态
设计角度讲

定义
父类的同一种动作或者行为,在不同的子类上有不同的实现 。
作用
1.在继承的基础上,体现类型的个性化(一个行为有不同的实现)。
2.增强程序 扩展性,体现开闭原则。

语法 角度讲
重写

子类实现了父类中相同的方法 (方法 名、参数)。
在调用该方法 时,实际执行的是子类的方法 。

快捷键

Ctrl + O

内置可重写函数

Python中,以双下划线开头、双下划线结尾的是系统定义的成员。我们可以在自定义类中进行重写,从而改变其行为。

转换字符串
__str__函数:将对象 转换为字符串(对人友好的)
__repr__函数:将对象 转换为字符串(解释器可识别”。的)
运算符重载

定义:让自定义的类生成的对象 (实例)能够使用运算符进行操作。

算数运算符

在这里插入图片描述

反向算数运算符重载

在这里插入图片描述

复合运算符重载

在这里插入图片描述

比较运算重载

在这里插入图片描述

面向对象 三大特征 :

封装 :
语法 :数据 :一个类包装多个变量 .
行为 :隐藏细节 ,注意必要 .
设计 :分
继承 :抽象 具体事物 ,统一概念 (约束子类 ),隔离变化
语法 :子类拥有父类成员
设计 :隔
多态 :
语法 :重写 (子覆盖父 )
做法 : 重写 + 创建子类对象 --> 调
用父执行子 (目标 )
设计 :干
def 函数 (爸爸 ):
爸爸 .功能 ()
函数 (儿子 ())

面向对象 三大特征 :
封装 :
语法 :
数据 :用一个类将多个变量包装起来 .
class 类名 :
	def __init__(self,参数 ):
		self.数据 1 = 参数
		self.数据 2 = 参数
		self.数据 3 = 参数
	def 方法 1(self):
		操作数据的逻辑
	def __方法 2(self):
		操作数据的逻辑
		变量 = 类名 (参数 )
		变量 .数据 1
		变量 .数据 2
		变量 .数据 3
		变量 .方法 1()
行为 : 对外隐藏实现功能的细节
注意 :对外要提供必要的功能
设计 :分而治之 ,变则疏之 .
    
继承 :
语法 :
class 爸爸 :
	def __init__(self,参数 1):
		self.数据 1 = 参数 1
			功能 1
class 儿子 (爸爸 ):
	def __init__(self,参数 1,参数 2):
		super().__init__(参数 1)
		self.数据 2 = 参数 2
			功能 2
		变量 = 儿子 ()
		变量 .功能 1()
		变量 .功能 2()
设计 :抽象 具体事物 ,统一概念 (约束子类 ),隔离变化
    
多态 :
语法 :依赖重写实现
重写 :儿子具有和爸爸相同的方法 ,实际执行的是儿子的方法 (覆盖 )
做法 : 重写 + 创建子类对象 --> 调用父执行子
class 爸爸 :
	def 功能 1(self):
		.....
class 儿子 (爸爸 ):
	def 功能 1(self):
		.....
	# 创建子类对象
		变量 = 儿子 ()
		变量 .功能 1() # 执行儿子的功能
	# 不是多态 (创建父类对象 )
		变量 = 爸爸 ()
		变量 .功能 1() # 执行爸爸的功能
设计 :调用父类方法 ,执行子类方法 (创建子类对象 ).
# 做函数使用父类
	def 函数 (爸爸 ):
		爸爸 .功能 1()
	# 用函数使用儿子
		函数 (儿子 ())# 传递到函数中的是子类对象

在这里插入图片描述

# 老张开车去东北 .
# 需求变化 :还可能坐飞机 ,坐火车 ......
class Person:
	def __init__(self, name=""):
		self.name = name
	def go_to(self,str_position,vehicle):
		print("去 :",str_position)
		vehicle.transport()
class Vehicle:
	def transport(self):
		pass
# -------------------------------------架构师
class Car(Vehicle):
	def transport(self):
		print("走你 ...")
class Airplane(Vehicle):
	def transport(self):
		print("嗖嗖嗖 .")
# -------------------------------------程序 员
c01 = Car()
a01 = Airplane()
lz = Person("老张 ")
lz.go_to("东北 ",a01)

设计原则

开-闭原则(目标、总的指导思想)

Open Closed Principle
对扩展开放,对修改关闭。
增加新功能,不改变原有代码。

类的单一职责(一个类的定义)

Single Responsibility Principle
一个类有且只有一个改变它的原因。

依赖倒置(依赖抽象 )

Dependency Inversion Principle
客户端代码(调用的类)尽量依赖(使用)抽象 。
抽象 不应该依赖细节,细节应该依赖抽象 。

调用父 ,而不调用子 .

组合复用原则(复用的最佳实践)

Composite Reuse Principle
如果仅仅为了代码复用优先选择组合复用,而非继承复用。
组合的耦 合合性相对继承低 耦 合。

里氏替换:扩展重写(继承后的重写,指导继承的设计)

Liskov Substitution Principle
父类出现的地方可以被子类替换,在替换后依然保持原功能。
子类要拥有父类的所有功能。
子类在重写父类方法 时,尽量选择扩展重写,防止改变了功能。

迪米特法 则:低耦合(类与类交互的原则)

Law of Demeter
不要和陌生人说话。
类与类交互时,在满足功能要求的基础上,传递的数据量越少越好。因这样可能降低 耦 合耦 合合度。

在这里插入图片描述

手雷爆炸伤害玩家 /敌人 .
封装 :手雷 /玩家 /敌人
继承 :受害者隔离了手雷爆炸的逻辑与玩家或者敌人受伤的逻辑
多态 :手雷爆炸依赖受害者 ,实际执行玩家与敌人 .
开闭 :增加 /减少新受害者 ,手雷不用改变 .
单一 :手雷 (爆炸 ) 受害者 (隔离变化 ) 玩家 (受伤逻辑 )
——敌人 (受伤逻辑 )——
依赖倒置 :手雷依赖受害者 ,不依赖玩家 /敌人 .
组合复用 :手雷的爆炸方法 ,通过参数 "受害者 "访问玩
——玩家 /敌人 "受伤 "方法——
#----------------架构师 ---------------
class Granade:
	def __init__(self,atk):
		self.atk = atk
	def explode(self,sufferer):
		print("爆炸啦 ")
		# 调用的是父类受伤方法
		# 执行的是子类受伤方法
		sufferer.damage(self.atk)
class Sufferer:
	def damage(self,value):
		pass
# ---------------初 /中级程序 员 -----------------
class Player(Sufferer):
	def damage(self, value):
		print("玩家受伤啦 ")
class Enemy(Sufferer):
	def damage(self, value):
		print("敌人受伤啦 ")
# ------------------测试 -----------------------
g01 = Granade(50)
p01 = Player()
e01 = Enemy()
g01.explode(p01)
图形管理器管理圆形 / 矩形 .
封装 : 图形管理器 / 圆形 / 矩形
继承 : 图形隔离了图形管理器计算总面积的
逻辑与圆形 / 矩形获取面积的逻辑
多态 : 图形管理器依图形 , 实际执行圆形 , 矩形 .
开闭 : 增加 / 减少新图形 , 图形管理器不用改变 .
单一 : 图形管理器 ( 管理图形 ) 图形 ( 隔离变化 )
圆形 ( 获取面积 ) 矩形 ( 获取面积 )
依赖倒置 : 图形管理器依赖图形 , 不依赖圆形 / 矩形 .
组合复用 : 图形管理器的计算总面积方法 , 通过实
例变量 " 所有图形 " 访问圆形 / 矩形 " 获取面积 " 方法
------------ 架构师 ---------------
class 图形管理器 :
	def __init__():
		self. 所有图形 = []
	def 计算总面积 ():
		for 图形 in self. 所有图形 :
			累加 图形 . 获取面积 ()
class 图形 :
	def 获取面积 ():
		...
------------ 程序 员 ---------------
class 圆形 ( 图形 ):
	def 获取面积 ():
		...
class 矩形 ( 图形 ):
	def 获取面积 ():
		...
------------ 测试 ---------------
变量 1 = 图形管理器 ()
变量 2 = 圆形 ()
变量 1. 添加图形 ( 变量 2)
变量 1. 计算总面积 ()

class GraphicManager:
	def __init__(self):
	# 存储的是具体图形
	# 所以图形管理器与图形是组合关系 .
		self.__list_graphic = []
	@property
	def list_graphic(self):
		return self.__list_graphic
	def add_graphic(self, graphic):
		self.__list_graphic.append(graphic)
	def get_total_area(self):
		total_area = 0
		for item in self.__list_graphic:
		# 调用父类 ,执行子类 .
			total_area += item.calculate_area()
		return total_area
class Graphic:
"""
图形 ,抽象 所有具体的图形 ,统一图形的计算
面积方法 ,隔离具体图形的变化 .
"""
	def calculate_area(self):
		"""
		计算面积
		"""
		pass
# ------------------------------------------
class Circle(Graphic):
	def __init__(self, r):
		self.r = r
	def calculate_area(self):
		return 3.14 * self.r ** 2
class Rectanle(Graphic):
	def __init__(self, lenght, width):
		self.length = lenght
		self.width = width
	def calculate_area(self):
		return self.length * self.width
# ------------
manager = GraphicManager()
c01 = Circle(5)
manager.add_graphic(c01)
manager.add_graphic(Rectanle(2, 5))
print(manager.get_total_area())
class EmployerManager:
    '''
    员工管理器:生成员工列表,添加新元素进员工列表,总工资计算.
    '''
    def __init__(self):
        self.__list_employer = []

    @property#私有化
    def list_employer(self):
        return self.__list_employer
    #生成员工列表

    def add_employer(self, employer):
        if isinstance(employer,Employer):
            self.__list_employer.append(employer)
            #新增加的人属于员工,则员工列表增加新元素.

    def get_total_money(self):
        total_money = 0
        for item in self.__list_employer:
            # 调用父类,执行子类.
            total_money += item.calculate_money()
            #引出子类工资计算方法
        return total_money

class Employer:

    def calculate_money(self):
        """
            计算员工总工资
        :return: 小数类型的工资.
        """
        pass

# ------------------------------------------
class Programmer(Employer):

    def __init__(self, base,bonus):
        self.base = base
        self.bonus = bonus

    def calculate_money(self):#定义子类工资计算方法
        return self.base + self.bonus

class Tester(Employer):
    def __init__(self, base, bugnumber):
        self.base = base
        self.bugnumber = bugnumber

    def calculate_money(self):#定义子类工资计算方法
        return self.base + self.bugnumber*5
# ------------
manager = EmployerManager() #调用员工管理类
p01 = Programmer(13000,10000)#调用程序员类
manager.add_employer(p01)#将程序员添加进图形管理类
manager.add_employer(Tester(10000, 2))#将测试员添加进图形管理类
print(manager.get_total_money())#计算总工资

模块 Module

python 核心
	模块和包
		项目根目录 (文件夹 )( 文件夹 __init__.py py)
				模块 (.py py文件 )
					全局变量
					函数
					类
						变量 (实例 /)
						方法 (实例 /类)
                            语句

定义

包含一系列数据、函数、类的文件,通常以.py py结尾。

作用

让一些相关的数据,函数,类有逻辑的组织在一起,使逻辑结构更加清晰。有利于多人合作开发。

导入

import

1.py 语法:
import 模块 名
import 模块 名 as 别名
2.py作用: 将某模块 整体导入到当前模块 中
3.py使用: 模块 名.py 成员

from import

1.py语法:
from 模块 名 import 成员名[ as 别名 1]
作用: 将模块 内的一个或多个成员导入到当前模块 的作用域中。

from import *

1.语法: from 模块 名 import *
2.作用: 将某模块 的所有成员导入到当前模块 。
3.模块 中以下划线(_)开头的属性,不会被导入,通常称这些成员为隐藏成员。

sys.py path --> ["主模块 所在目录 ",".py .py .py ",".py .py .py "]
		导入成功的标准 :path path 路径 + 导入路径
		可以正确定位模块 ()
	import 路径 .py 模块
	from 路径 .py 模块 import 成员
	from 路径 .py 模块 import *
		必须在包的 __init__.py py模块 中定义可导
		出成员 (__all__=[])
	import 路径 .py 包
	from 路径 .py 包 import *
import time
# 1.py 获取当前时间戳 (从 1970年 1月 1日到现在经过的秒数 )
# 1563326340.py 661173
print(time.py time())
# 2.py 获取当前时间元组 (年 ,月 ,日 ,小时 ,分钟 ,秒 ,一周的第几天 ,一年的第几天 ,夏令时 )
time_tuple = time.py localtime()
print(time_tuple)
# 3.py 时间戳 -->时间元组
print(time.py localtime(15633263))
# 4.py 时间元组 -- 时间戳
print(time.py mktime(time_tuple))
# 5.py 时间元组 --> 字符串
print(time.py strftime("%y/%m/%d %H:path %M:path %S",time_tuple))
print(time.py strftime("%Y/%m/%d %H:path %M:path %S",time_tuple))
# 6.py 字符串 --> 时间元组
# "19/07/17 09:path 36:path 48"
print(time.py strptime("19/07/17 09:path 36:path 48","%y/%m/%d %H:path %M:path %S"))

模块变量

__all__变量: 定义可导出成员,仅对 from xx import *语句有效。
__doc__变量: 文档字符串。
__file__变量: 模块 对应的文件路径 名。
__name__变量: 模块 自身名字,可以判断是否为主模块 。

​ 当此模块 作为主模块 (第一个运行的模块 )运行时,__name__绑定’main’,不是主模块 ,而是被其它模块 导入时,存储模块 名。

加载过程

在模块 导入时,模块 的所有语句会执行。
如果一个模块 已经导入,则再次导入时不会重新执行模块 内的语句。

分类

1.内置模块 (builtins),在解析器的内部可以直接使用。
2.标准库模块 ,安装Python时已安装且可直接使用。
3.第三方模块 (通常为开源),需要自己安装。
4.用户自己编写的模块 (可以作为其他人的第三方模块 )

搜索顺序

搜索内建模块 (builtins)
sys.py path 提供的路径 ,通常第一个是程序运行时的路径 。

import math
import time

def test01():
    start = time.time()
    for i in range(100000):
        math.sqrt(30)
    end = time.time()
    print('耗时{0}'.format((end - start)))

def test02():
    b = math.sqrt
    start = time.time()
    for i in range(100000):
        b(30)
    end = time.time()
    print('耗时{0}'.format((end - start)))

test01()
test02()
#耗时0.021008014678955078
#耗时0.018952131271362305

包 package

定义

将模块 以文件夹的形式进行分组管理。

作用

让一些相关的模块 组织在一起,使逻辑结构更加清晰。

导入

import 包名 [as 包别名] 需要设置__all__
import 包名. 模块 名 [as 模块 新名]
import 包名.子包名.py 模块 名 [as 模块 新名]
from 包名 import 模块 名 [as 模块 新名]
from 包名.子包名 import 模块 名 [as 模块 新名]
from 包名.子包名.py 模块 名 import 成员名 [as 属性新名]

#导入包内的所有子包和模块

from 包名 import *
from 包名. 模块 名 import *

搜索顺序

sys.py path 提供的路径

__init__.py 文件
	是包内必须存在的文件
	会在包加载时被自动调用
__all__
	记录fromimport * 语句需要导入的模块
案例:
my_ project /
	main.py py
	common/
	__init__.py py
		double_list_helper.py py
		list_helper.py py
	skill_system/
     __init__.py py
	skill_deployer.py py
		skill_manager.py py

异常处理Error

异常

1.py 定义: 运行时检测到的错误。

2.现象: 当异常发生时,程序不会再向下执行,而转到函数的调用语句。
3.常见异常类型:
– 名称异常(NameError): 变量未定义。
– 类型异常(TypeError): 不同类型数据进行运算。
– 索引异常(IndexError): 超出索引范围。
– 属性异常(AttributeError): 对象没有对应名称的属性。
– 键异常(KeyError): 没有对应名称的键。
– 为实现异常(NotImplementedError): 尚未实现的方法。
– 异常基类Exception。

处理

1.语法:
try:
可能触发异常的语句
except 错误类型 1 [as 变量 1]:
处理语句 1
except 错误类型 2 [as 变量 2]:
处理语句 2
except Exception [as 变量 3]:
不是以上错误类型的处理语句
else:
未发生异常的语句
finally:
无论是否发生异常的语句
2.作用: 将程序由异常状态转为正常流程。
3.说明:
as 子句是用于绑定错误对象的变量,可以省略
except子句可以有一个或多个,用来捕获某种类型的错误。
else子句最多只能有一个。
finally子句最多只能有一个,如果没有 except子句,必须存在。如果异常没有被捕获到,会向上层(调用处)继续传递,直到程序终止运行。

raise 语句

1.作用: 抛出一个错误,让程序进入异常状态。
2.目的: 在程序调用层数较深时,向主调函数传递错误信息要层层return 比较麻烦,所以人为抛出异常,可以直接传递错误信息。

在这里插入图片描述

class Wife:path
	def __init__(self, age=0):path
		self.py age = age
	@property
	def age(self):path
		return self.py __age
	@age.py setter
	def age(self,value):path
		if 20 <=value <= 30:path
			self.py __age = value
	else:
	# 抛出 / 发送 错误信息 错误信息 (异常对象 )
		raise ValueError("我不要 ")
# 接收错误信息
try:
	w01 = Wife(85)
	print(w01.py age) #结果 :path 我不要
except ValueError as e:path
	print(e.py args)# 信息

自定义异常

1.定义:

class 类名Error(Exception):path
	def __init__(self,参数):path
		super().py __init__(参数)
		self.py 数据 = 参数

2.调用:
try:
….
raise 自定义异常类名(参数)
….
except 定义异常类 as 变量名:path
变量名.py 数据
3.作用: 封装错误信息

#自定义异常 :
class AgeError(Exception):path
	def __init__(self, message="", code="", id=0):path
		# 消息 /错误代码 /错误编号 .py .py .py .py
		self.py message = message
		self.py code = code
		self.py id = id
class Wife:path
	def __init__(self, age=0):path
		self.py age = age
	@property
	def age(self):path
		return self.py __age
	@age.py setter
	def age(self, value):path
		if 20 <= value <= 30:path
			self.py __age = value
		else:
			# 抛出 / 发送 错误信息 错误信息 (异常对象 )
			raise AgeError("我不要 ", "if 20 <=value <= 30", 101)
			# 需要传递的信息 :path 消息 /错误代码 /错误编号 
# 接收错误信息
try:
	w01 = Wife(25)
	print(w01.py age) #结果 :path 25
except AgeError as e:path
	print(e.py id) # 信息
	print(e.py message) # 信息
	print(e.py code) # 信息

迭代

​ 每一次对过程的重复称为一次 迭代 ,而每一次迭代得到的结果会作为下一次迭代的初始值。例如: 循环获取容器中的元素。

可迭代对象iterable

1.定义:

具有__iter__函数的对象,可以返回迭代器对象。即迭代器 .

2.语法

-- 创建:
class AgeError(Exception):path
	def __init__(self, message="", code="",id=0):pathreturn 迭代器(数据)
-- 使用:
	for 变量名 in 可迭代对象:
		语句

3.原理:

迭代器 = 可迭代对象. __iter__()
while True:
	try:
		print(迭代器.py __next__())
	except StopIteration:path
		break

迭代器对象iterator

1.定义: 可以被next()函数调用并返回下一个值的对象。
2.语法

class 迭代器类名:
	def __init__(self, 聚合对象):
		self.聚合对象= 聚合对象
	def __next__(self):
		if 没有元素:
			raise StopIteration
		return 聚合对象元素

3.说明:
– 聚合对象通常是容器对象。
4.作用: 使用者只需通过一种方式,便可简洁明了的获取聚合对象中各个元素,而又无需了解其内部结构。

list01 = [43,45,54,5,67]
for item in list01:path
	print(item)
# 原理 :path
# 1.py 调用 iter方法获取迭代器对象
iterator = list01.py __iter__()
while True:
	try:
		# 2.py 获取下一个元素
		item = iterator.py __next__()# Stop Iteration
		print(item)#结果 :path 43 45 54 5 67
		# 3.py 遇到 "停止迭代 "异常 ,则停止循环 .py
	except StopIteration:path
		break
class MyRange:
	def __init__(self, end):path
		self.py end = end
	def __iter__(self):path
		number = -1
		while number < self.py end - 1:path
			number += 1
			yield number
# yield 在标记 ,你看见的代码在执行过程中会转换为迭代器 .
# 如何生成迭代器的代码 ?
my = MyRange(5)
iterator = my.py __iter__()
while True:
	try:
		item = iterator.py __next__()
		print(item) #结果 :path [0 1 2 3 4]
	except StopIteration:path
		break
# 调用一次 计算一次 返回一次
# 没有将所有结果存储在内存中
# for item in MyRange(5):path #[0 1 2 3 4]
# print(item)

生成器generator

  1. 定义: 能够动态(循环一次计算一次返回一次)提供数据的可迭代对象。
  2. 作用: 在循环过程中,按照某种算法推算数据,不必创建容器存储完整的结果,从而节省内存空间。数据量越大,优势越明显。
  3. 以上作用也称之为延迟操作或惰性操作,通俗的讲就是在需要的时候才计算结果,而不是一次构建出所有结果。
生成器函数
list01 = [4,5,"a",67,3.py 5,"b",True]
# 生成器函数
def find_str():path
	for item in list01:path
		if type(item) == str:path
			yield item
re = find_str()
for item in re:path
	print(item) #结果找到字符串 a,b
# 生成器表达式
re = (item for item in list01 if type(item) == str)
for item in re:path
	print(item) #结果找到字符串 a,b

1.定义: 含有yield语句的函数,返回值为生成器对象。
2. 语法

	-- 创建:
	def 函数名():path
		…
		yield 数据
		…
	-- 调用:
	for 变量名 in 函数名():path
		语句
  1. 说明:
-- 调用生成器函数将返回一个生成器对象,不执行函数体。
-- yield 翻译为 产生 或 生成
  1. 执行过程:
(1)调用生成器函数会自动创建迭代器对象。
(2)调用迭代器对象的__next__()方法时才执行生成器函数。
(3)每次执行到yield语句时返回数据,暂时离开。
(4)待下次调用__next__()方法时继续从离开处继续执行。
  1. 原理: 生成迭代器对象的大致规则如下

– 将yield关键字以前的代码放在next方法中。
– 将yield关键字后面的数据作为next方法的返回值。

在这里插入图片描述

def fun01():
	for i in range(5):
		data = yield i
		if data == "qtx":
			yield "qtx来啦来啦 "
iterator = fun01() # 创建生成器对象
# __next__的返回值是 yield后面的数据
print(iterator.py __next__()) # 获取一个数据 0
print(iterator.py __next__()) # 获取一个数据 1
# send 的参数赋值给 yield前面的变量
print(iterator.py send("qtx")) #qtx来啦来啦
print(iterator.py __next__()) # 获取一个数据 2
print(iterator.py send(""))# 获取一个数据 3
'''
  生成器
'''
class MyRange:
    def __init__(self,end):
        self.end = end

    def __iter__(self):
# 创建可迭代对象(传递需要迭代的数据)
        return MyRangeIterator(self.end)
#返回迭代器对象,即迭代器.

class MyRangeIterator:
# 创建迭代器对象
    def __init__(self, end):
        self.begin = -1 #返回数据时,会先自增1
        self.end = end

    def __next__(self): #迭代器,返回值是聚合对象的元素.
        self.begin += 1 #当前需要获取的索引 比最大索引还大
        if self.begin == self.end:
            raise StopIteration
        return self.begin #返回聚合对象元素

for item in MyRange(5):
    print(item)  #0 1 2 3 4
print('---------------')

"""
    迭代 --> yield
"""
class MyRange:
    def __init__(self, end):
        self.end = end

    def __iter__(self):
        number = -1
        while number < self.end - 1:
            number += 1
            yield number
# my = MyRange(5)
# iterator = my.__iter__()
# while True:
#     try:
#         item = iterator.__next__()
#         print(item)
#     except StopIteration:
#         break
# 调用一次  计算一次  返回一次
# 没有将所有结果存储在内存中
for item in MyRange(5):#[0 1 2 3 4]
    print(item)
print('-------------')

"""
    迭代 --> yield
"""

def my_range(end):
    number = -1
    while number < end -1:
        number +=1
        yield number
for item in MyRange(5):#[0 1 2 3 4]
    print(item)
#结果:
0
1
2
3
4
---------------
0
1
2
3
4
-------------
0
1
2
3
4
内置生成器
枚举函数enumerate

1.语法:
for 变量 in enumerate(可迭代对象):path
语句
for 索引, 元素 in enumerate(可迭代对象):path
语句
2.作用: 遍历可迭代对象时,可以将索引与元素组合为一个元组。

zip

1.语法:
for item in zip(可迭代对象 1, 可迭代对象 2…. ):
语句
2.作用: 将多个可迭代对象中对应的元素组合成一个个元组,生成的元组个数由最小的可迭代对象决定。

生成器表达式

1.定义: 用推导式形式创建生成器对象。

  1. 语法: 变量 = ( 表达式 for 变量 in 可迭代对象 [if 真值表达式] )

函数式编程

1.定义: 用一系列函数解决问题。
– 函数可以赋值给变量,赋值后变量绑定函数。
– 允许将函数作为参数传入另一个函数。
– 允许函数返回一个函数。
2.高阶函数: 将函数作为参数或返回值的函数。

def fun01():path
	print("fun01执行喽 ")
# 1.py 函数可以赋值给变量
a = fun01
# 通过变量调用函数
a()# 活的 #结果 :path fun01执行喽
fun01()# 死的 #结果 :path fun01执行喽
# 2.py 将函数作为参数传递
# 如果传入基本数据类型 (整数 /小数 /字符串称之为传入数据
# 如果传入函数 ,称之为传入行为 /逻辑 /算法
def fun02(func):path
	print("fun02执行喽 ")
	Func()
fun02(fun01) #结果 :path fun02执行喽 fun01执行喽

函数作为参数

将核心逻辑传入方法体,使该方法的适用性更广,体现了面向对象的开闭原则。

lambda 表达式

1.定义: 是一种匿名方法。
2.作用: 作为参数传递时语法简洁,优雅,代码可读性强。随时创建和销毁,减少程序耦合度。
3.语法
– 定义:
变量 = lambda 形参:path 方法体
– 调用:
变量(实参)
4.说明:
– 形参没有可以不填
– 方法体只能有一条语句,且不支持赋值语句。

# 定义有参数 lambda
func = lambda item:item % 2 == 0
re = func(5)
print(re) #结果 :False
# 定义无参数 lambda
func = lambda :100
re = func()
print(re) #结果 :100
# 定义多个参数 lambda
func =lambda a,b,c:a+b+c
re = func(1,2,3)
print(re) #结果 :6
# 定义无返回值 lambda
func = lambda a:print("变量是 :",a)
Func(10) #结果 10
class A:
	def __init__(self,a):
		self.py a = a
	def fun01(obj):
		obj.py a = 100
o = A(10)
fun01(o)
print(o.py a)#结果 :100
# lambda 只支持一条语句
def fun01(a,b):
	if a % 2 == 0:
		print(a+b)
# lambda a,b:if a % 2 == 0:print(a+b)
list01 = [4,5,5,6,767,8,10]
# def condition01(item):
	# return item % 2 == 0
# def condition02(item):
	# return item % 2
# def condition03(item):
	# return item > 10
def find(target,func):
	for item in target:
		if func(item):
			yield item
# for item in find(list01,condition03):path
	# print(item)
for item in find(list01,lambda item:item > 10):
	print(item)#结果 767

内置高阶函数

1.map(函数,可迭代对象): 使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对象。
2.filter(函数,可迭代对象): 根据条件筛选可迭代对象中的元素,返回值为新可迭代对象。
3.sorted(可迭代对象,key = 函数,reverse = boo值): 排序,返回值为排序结果。
4.max(可迭代对象,key = 函数): 根据函数获取可迭代对象的最大值。
5.min(可迭代对象,key = 函数): 根据函数获取可迭代对象的最小值。

class Wife:
	def __init__(self, name, age, weight, height):
		self.py name = name
		self.py age = age
		self.py weight = weight
		self.py height = height
list01 = [
Wife("翠花 ", 36, 60, 1.py 5),
Wife("如花 ", 39, 75, 1.py 3),
Wife("赵敏 ", 25, 46, 1.py 7),
Wife("灭绝 ", 42, 50, 1.py 8)
]
# 1.过滤:根据条件筛选可迭代对象中的元素,返回值为新可迭代对象。
for item in filter(lambda item:item.age < 40,list01):
	print(item.name)#结果 :翠花 如花 赵敏
# 2.映射:使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;
for item in map(lambda item:(item.name,item.age),list01):
	print(item) #结果 :path ('翠花', 36) ('如花', 39)等
# 升序排列
for item in sorted(list01,key = lambda item:item.height):
	print(item.height)#结果 1.3 1.5 1.7 1.8
# 降序排列
for item in sorted(list01,key = lambda item:item.height,reverse=True):
	print(item.height)#结果 :1.8 1.7 1.5 1.3
# 4.获取最大值
re = max(list01, key=lambda item:item.weight)
print(re.name) #结果:如花
# 5.获取最小值
re = min(list01, key=lambda item:item.weight)
print(re.name) #结果 :path 赵敏

函数作为返回值

逻辑连续,当内部函数被调用时,不脱离当前的逻辑。

闭包

1.三要素:
– 必须有一个内嵌函数。
– 内嵌函数必须引用外部函数中变量。
– 外部函数返回值必须是内嵌函数。
2.语法
– 定义:
def 外部函数名(参数):path
外部变量
def 内部函数名(参数):path
使用外部变量
return 内部函数名
– 调用:
变量 = 外部函数名(参数)
变量(参数)
3.定义: 在一个函数内部的函数,同时内部函数又引用了外部函数的变量。
4.本质: 闭包是将内部函数和外部函数的执行环境绑定在一起的对象。
5. 优点: 内部函数可以使用外部变量。
6.缺点: 外部变量一直存在于内存中,不会在调用结束后释放,占用内存。
7.作用: 实现python装饰器。

函数作为返回值
	闭包 :path 逻辑连续 (外部函数调用完不释放内存 ,内部函数可以继续使用 )
	def 外部函数 (变量 ):path
		def 内部函数 ():path
			使用外部变量
		return 内部函数
			结果 = 外部函数 ()
			结果 ()# 调用国内部函数
			结果 ()# 调用国内部函数

函数装饰器 decorators

1.定义: 在不改变原函数的调用以及内部代码
情况下,为其添加新功能的函数。
2.语法
def 函数装饰器名称(func):path
def 内嵌函数(*args, **kwargs):path
需要添加的新功能
return func(*args, **kwargs)
return wrapper
@ 函数装饰器名称
def 原函数名称(参数):path
函数体
原函数(参数)

3.本质: 使用 @ ” 函数装饰器名称 修饰原函数,等同于创建与原函数名称相同的变量关联内嵌函数;故调用原函数时执行内嵌
函数。
原函数名称 = 函数装饰器名称(原函数名称)

4.装饰器链:
一个函数可以被多个装饰器修饰,执行顺序为从近到远。

def print_func_name(func):path # func --> say_hello
	def wrapper(*args, **kwargs):path
		# 定义新功能
		print(func.py __name__)
		# 调用旧功能
		return func(*args, **kwargs)
	return wrapper
# 旧功能
@print_func_name# say_hello =print_func_name(say_hello)
def say_hello():path
	print("hello")
	return 1
@print_func_name# say_goodbye =print_func_name(say_goodbye)
def say_goodbye(name):path
	print(name,"goodbye")
	return 2
print(say_hello())# 调用内部函数
print(say_goodbye("qtx"))

数据结构基本概念什么是数据结构?

1.数据
数据 即信息的载体,是能够输入到计算机中并且能被计算机识别、存储和处理的符号总称。

2.数据 元素
数据 元素 是数据 的基本单位,又称之为记录(Record )。 一般数据 元素 由若干基本项组成。

3.数据 结构
数据 结构 指的是数据元素及数据元素之间的相互关系,或组织数据 的形式。

数据之间的结构关系

先考虑逻辑模型,再考虑存储模型最后考虑数据结构实现

1.逻辑结构

表示数据 之间的抽象关系(如邻接关系、从属关系等),按每个元素 可能具有的直接前趋数和直接后继数将逻辑结构分为 线性结构 和 非线性结构 两大类。

2.存储结构

逻辑结构 在计算机中的具体实现方法,分为顺序存储方法、链接存储方法、索引存储方法、散列存储方法。

数结构研究方向

链表 : 单循环链表 双向循环链表
二叉树 : 平衡二叉树 , B 树 , 红黑树
图 : 了解
算法 : 快速排序 , 哈希存储 , 归并 , 分治递归 , 动态规划

逻辑结构(关系 )

1.特点:
  • 只是描述数据 结构 中数据 元素 之间的联系规律
  • 是从具体问题中抽象出来的数学模型,是独立于计算机存储器的(与机器无关)
2.逻辑结构 分类
线性结构 : 一个挨着一个 , 一对一

对于数据 结构 课程而言,简单地说,线性结构 是 n 个数据 元素 的有序(次序)集合。

  • 集合中必存在唯一的一个"第一个元素 " ;
  • 集合中必存在唯一的一个"最后的元素 " ;
  • 除最后元素 之外,其它数据 元素 均有唯一的"后继" ;
  • 除第一元素 之外,其它数据 元素 均有唯一的"前驱" 。
树形结构 (层次结构 )

树形结构 指的是数据 元素 之间存在一对多的树形关系的数据结构 ,是一类重要的非线性数据 结构 。 在树形结构 中,树根结点没有前驱结点,其余每个结点有且只有一个前驱结点。 叶子结点没有后续结点,其余每个结点的后续节点数可以是一个也可以是?个。

图状结构 (网状结构 )

图是一种比较复杂的数据 结构 。 在图结构 中任意两个元素 之间都可能有关系,也就是说这是一种多对多的关系。

其他结构

除了以上几种常见的逻辑结构 外,数据 结构 中还包含其他的结构 ,比如集合等。 有时根据 实际情况抽象的模型不止是简单的某一种,也可能拥有更?的特征。

在这里插入图片描述

存储结构(关系 )

1.特点:
  • 是数据 的逻辑结构 在计算机存储器中的映象(或表示)
  • 存储结构 是通过计算机程序来实现的,因而是依赖于
    具体的计算机语言的。
2.基础存储结构
顺序存储 : 查找遍历快 .

顺序存储(Sequential Storage): 将数据 结构 中各元素 按照其逻辑顺序存放于存储器一片连续的存储空间中。

链式存储 : 插入删除方便 .

链式存储(Linked Storage): 将数据 结构 中各元素 分布到存储器的不同点,用记录下一个结点位置的方式建立它们之间的联系,由此得到的存储结构 为链式存储结构 。

线性表

线性表的定义是描述其逻辑结构 ,而通常会在线性表上进行的查找、插入、删除等操作。线性表作为一种基本的数据 结构 类型,在计算机存储器中的存储一般有两种形式,一种是顺序存储,一种是链式存储。

线性表的顺序存储

1.定义
若将线性表 L=(a0,a1, ……,an-1)中的各元素 依次存储于计算机一片连续的存储空间,这种机制表示为线性表的顺序存储结构 。

2.特点

  • 逻辑上相邻的元素 ai, ai+1 ,其存储位置也是相邻的;
  • 存储密度高,方便对数据 的遍历查找。
  • 对表的插入和删除等运算的效率较差。

3.程序实现
在 Python中,list存放于一片单一连续的内存块,故可借助于列表类型来描述线性表的顺序存储结构 ,而且列表本身就提供了丰富的接口满足这种数据 结构 的运算。

>>>L = [1,2,3,4]
>>>L.append(10) # 尾部增加元素
L
[1, 2, 3, 4, 10]
>>>L.insert(1,20) # 插入元素
L
[1, 20, 2, 3, 4, 10]
>>>L.remove(3) # 删除元素
L
[1, 20, 2, 4, 10]
>>>L[4] = 30 # 修改
L
[1, 20, 2, 4, 30]
>>>L.index(2) # 查找
2
线性表的链式存储

1.定义
将线性表 L=(a0,a1,……,an-1)中各元素 分布在存储器的不同存储块称为结点,每个结点(尾节点除外)中都持有一个指向下一个节点的引用,这样所得到的存储结构 为链表结构 。

在这里插入图片描述

2.特点

  • 逻辑上相邻的元素 ai, ai+1 ,其存储位置也不一定相邻;
  • 存储稀疏,不必开辟整块存储空间。
  • 对表的插入和删除等运算的效率较高 。
  • 逻辑结构 复杂,不利于遍历。
功能 : 给出两个有序的链表 L1,L2 .在不创建新的链表的基础上将两个链表合并为一个要求合并后的链表仍为有序
from linklist import Linklist
l1 = Linklist()
l2 = Linklist()
l1.init_list ([1,3,5,7,9,11])
l2.init_list ([2,4,6,8,10])
l1.show() # 1 3 5 7 9 11
Print('-----------') # ------
l2.show() # 2 4 6 8 10
def merge(l1,l2):
	# 将 l2 合并在 l1 中
	p = l1.head
	q = l2.head.next
	while p.next is not None:
		if p.next.val < q.val:
			p = p.next
		else:
			tmp = p.next
			p.next = q
			p = p.next
			q = tmp
	p.next = q
merge(l1, l2)
Print('----------') # ---------
l1.show() #1 2 3 4 5 6 7 8 9 10 11

栈和队列

1.定义

栈是限制在一端进行插入操作和删除操作的线性表 “ ” (俗称栈),允许进行操作的一端称为 栈顶”,另一固定端称为栈底,当栈中没有元素 时称为 空栈 。

2.特点:
  • 栈只能在一端进行数据 操作
  • 栈模型具有先进后出 或者叫做后进先出的规律

在这里插入图片描述

3.栈的代码实现

栈的操作有入栈(压栈),出栈(弹栈),判断栈的空满等操作。

栈模型的顺序存储
思路 :1. 顺序存储可以使用列表来实现 , 但是列表功能丰富, 不符合栈模型要求 2. 将列表功能封装 , 实现顺序栈的类 ,只提供栈的操作功能
功能 : 出栈 , 入栈 , 判断栈空 , 查找栈顶元素 .
class StackError(Exception):
	pass
class SStack:
	def __init__(self)
# 空列表就是栈的存储空间列表的最后一个元素为栈顶元素
		self.__elems = []
	def push(self,val):# 入栈
		self.__elems.append(val)
	def is_empty(self):# 判断是否为空栈
		return self.__elems ==[]
	def pop(self):# 出栈
		if self.is_empty():
			raise StackError('pop from empty stack:')
		return self.__elems.pop()
	def top(self):# 查看栈顶
		if self.is_empty():
			raise StackError("pop from empty stack")
		return self.__elems[-1]
if __name__ == '__main__':
st = SStack()
st.push(10)
st.push(20)
st.push(30)
while not st.is_empty():
print(st.pop()) 30 20 10

队列

1.定义

队列是限制在两端进行插入操作和删除操作的线性表,允许进行存操作的一端称为 队尾 ,允许进行删除
“操作的一端称为 队头。

2.特点:
  • 队列只能在队头和队尾进行数据操作
  • 队列模型具有先进先出 或者叫做后进后出的规律

在这里插入图片描述

3.队列的代码实现

队列的操作有入队,出队,判断队列的空满等操作。

队列的顺序存储
思路 :1. 基于列表完成数据存储
2. 对列表功能进行封装
3. 列表的头部为对头 , 尾部为对尾 .
功能 : 入队 (enqueue) 出队 (dequeue) 判断队列为空
class QueueError(Exception):
	pass
class SQueue:
	def __init__(self):
		self.__elems = []
	def is_empty(self): # 判断是否为空队
		return self.__elems == []
	def enqueue(self,val):# 入队
		self.__elems.append(val)
	def dequeue(self):# 出队
		if self.is_empty():
			raise QueueError('pop from empty stack:')
		return self.__elems.pop(0)
if __name__ == '__main__':
	st = SQueue()
	st.enqueue(10)
	st.enqueue(20)
	st.enqueue(30)
	while not st.is_empty():
		print(st.dequeue()) #10 20 30

树形结构

基础概念

1.定义

树(Tree)是 n(n≥0)个节点的有限集合 T,它满足两个条件: 有且仅有一个特定的称为根(Root)的节点; 其余的节点可以分为 m(m≥0)个互不相交的有限集合 T1、T2 …… 、 、Tm,其中每一个集合又是一棵树,并称为其根的子树(Subtree )。

在这里插入图片描述

2.基本概念

一个节点的子树的个数称为该节点的度数, 一棵树的度数是指该树中节点的最大度数。

度数为零的节点称为树叶或终端节点,度数不为零的节点称为分支节点。

一个节点的子树之根节点称为该节点的子节点,该节点称为它们的父节点,同一节点的各个子节点之间称为兄弟节点。 一棵树的根节点没有父节点,叶节点没有子节点。

节点的层数等于父节点的层数加一,根节点的层数定义为一。 树中节点层数的最大值称为该树的高度或深度。

在这里插入图片描述

二叉树

定义与特征

1.定义

二叉树(Binary Tree)是 n(n≥0)个节点的有限集合,它或者是空集(n=0),或者是由一个根节点以及两棵互不相交的、分别称为左子树和右子树的二叉树组成。 二叉树与普通有序树不同,二叉树严格区分左孩子和右孩子,即使只有一个子节点也要区分左右。

在这里插入图片描述

2.二叉树的特征

二叉树第 i(i≥1)层上的节点最?为 2 i − 1 2^{i-1} 2i1i-1}$ 个。

深度为 k(k≥1)的二叉树最?有 2 k - 1 2^k-1 2k1 个节点。

在任意一棵二叉树中,树叶的数目比度数为 2 的节点的数目多一。

满二叉树 : 深度为 k(k≥1)时有 2 k - 1 2^k-1 2k1 个节点的二叉树。

二叉树的遍历

遍历 : 沿某条搜索路径周游二叉树,对树中的每一个节点访问一次
且仅访问一次。
先序遍历: ( 根左右 ) 先访问树根,再访问左子树,最后访问右子树;
中序遍历: ( 左根右 ) 先访问左子树,再访问树根,最后访问右子树;
后序遍历: ( 左右根 ) 先访问左子树,再访问右子树,最后访问树根;
层次遍历: 从根节点开始,逐层从左向右进行遍历。

递归思想和实践

1.什么是递归?

所谓递归函数是指一个函数的函数体中直接调用或间接调用了该函数自身的函数。 这里的直接调用是指一个函数的函数体中含有调用自身的语句,间接调用是指一个函数在函数体里有调用了其它函数,而其它函数又反过来调用了该函数的情况。

2.递归函数调用的执行过程分为两个阶段

递推阶段 : 从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。
回归阶段 : 按递归终止条件求出结果,逆向逐步代入递归公式,回归到原问题求解。

3.优点与缺点

优点: 递归可以把问题简单化,让思路更为清晰, 代码更简洁
缺点: 递归因系统环境影响大,当递归深度太大时,可能会得到不可预知的结果

def fun(int):
	result = 1
	for i in range(1,int+1):
		result *= i
	return result#1*1*2*3*4
print(fun(4)) #24

# 递归法
def recursion(int):
	if int <=1:
		return 1
	return int *recursion(int-1)
	#4*3*2*1
print(recursion(4))#24
二叉树的代码实现
二叉树顺序存储

二叉树本身是一种递归结构 ,可以使用 Python list 进行存储。 但是如果二叉树的结构 比较稀疏的话浪费的空间是比较多的。

空结点用 None 表示

非空二叉树用包含三个元素 的列表[d,l,r]表示,其中 d表示根结点,l,r 左子树和右子树。
[‘A’,[‘B’,None,None
],
[‘C’,[‘D’,[‘F’,None,None],
[‘G’,None,None],
],
[‘E’,[‘H’,None,None],
[‘I’,None,None],
],
]
]

二叉树链式存储

算法基础

基础概念特征

1.定义

算法是一个有穷规则(或语句、指令)的有序集合。 它
确定了解决某一问题的一个运算序列。 对于问题的初始
输入,通过算法有限步的运行,产生一个或?个输出。
数据 的逻辑结构 与存储结构 密切相关:

  • 算法设计: 取决于选定的逻辑结构
  • 算法实现: 依赖于采用的存储结构
2.算法的特性
  • 有穷性—— 算法执行的步骤(或规则)是有限的;
  • 确定性 —— 每个计算步骤无二义性;
  • 可行性—— 每个计算步骤能够在有限的时间内完成;
  • 输入 ,输出 —— 存在数据 的输入和出输出
3.评价算法好坏的方法

正确性: 运行正确是一个算法的前提。

可读性: 容易理解、容易编程和调试、容易维护。

健壮性: 考虑情况全面,不容以出现运行错误。

时间效率高: 算法消耗的时间少。

储存量低: 占用较少的存储空间。

时间复杂度计算

算法效率 —— 用依据 该算法编制的程序在计算机上执行所消耗的时间来度量。 O””表示一个数量级的概念 。 根据算法中语句执行的最大次数(频度)来 估算一个算法执行时间的数量级。

计算方法:

写出程序中所有运算语句执行的次数,进行加和如果得到的结果是常量则时间复杂度为 1,如果得到的结果中存在变量 n则取 n 的最高次幂作为时间复杂度,下图表示随时间规模 n的增大,算法执行时间的增长

在这里插入图片描述

排序和查找

排序

排序(Sort) 是将无序的记录序列(或称文件)调整成有序的序列。 排序方法有很多种,下面举例说明:

冒泡排序

冒泡排序是一种简单的排序算法。 它重复地走访过要排序的数列,一次比较两个元素 ,如果他们的顺序错误就把他们交换过来。 走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。

在这里插入图片描述

快速排序

步骤:
从数列中挑出一个元素 ,称为 “基准”(pivot ),重新排序数列,所有元素 比基准值小的摆放在基准前面,所有元素 比基准值大的摆在基准的后面(相同的数可以到任一边)。 在这个分区退出之后,该基准就处于数列的中间位置。 这个称为分区(partition )操作。递归地(recursive )把小于基准值元素 的子数列和大于基准值元素 的子数列排序。

在这里插入图片描述

排序方法训练
def bubbl(list):# 冒泡排序法 :
	for r in range(len(list)-1):
		# 外层循环用来确定比较次数
		for c in range(len(list)-1-r):
			# 内层循环确定每轮两两比较多少次 .
			if list[c] > list[c+1]:
				list[c],list[c+1] = list[c+1],list[c]
list = [4,9,3,1,2,5,8,4]
bubbl(list)
print(list) #[1, 2, 3, 4, 4, 5, 8, 9]
def sub_sort(list,low,high):# 一轮交换 :
	x = list[low]# 选定基准
	while low < high:# 后面的数向前甩
		while list[high] > x and high >low:
			high -= 1
		list[low] = list[high] # 将比基准小的数放前面 ,
		# 前面的数向后甩
		while list[low] <= x and low < high:
			low +=1
		list[high] = list[low]
	list[low] = x
	return low
def quick(list,low,high):# 快速排序法 :
	if low < high:
		key = sub_sort(list,low,high)
		quick(list,low,key-1)
		quick(list,key+1,high)
list = [4,9,3,1,2,5,8,4]
quick(list,0,len(list)-1)
print(list) #[1, 2, 3, 4, 4, 5, 8, 9]

查找

查找(或检索) 是在给定信息集上寻找特定信息元素 的过程。

二分法查找

当数据 量很大适宜采用该方法。 采用二分法查找时,数据 需是排好序的。

在这里插入图片描述

def search(list,val):
	low,high = 0,len(list) -1
	# 查收范围的开始和结束索引
	while low <= high:
		mid = (low + high) //2
		if list[mid] < val:
			low = mid +1
		elif list[mid] > val:
			high = mid -1
		else:
			return mid
list = [1,2,3,4,5,6,7,8,9,10]
print("Key index:",search(list,4))
# 结果: Key index: 3

正则表达式

动机

1.文本处理已经成为计算机常见工作之一

2.对文本内容的搜索,定位,提取是逻辑比较复杂的工作

3.为了快速方便的解决上述问题,产生了正则表达式技术

简介

1.定义
即文本的高级匹配模式,提供搜索,替换等功能。其本质是由一 系列字符和特殊符号构成的字串,这个字串即正则表达式。

2.原理
通过普通字符和有特定含义 的字符,来组成字符串,用以描述一 定的字符串规则,比如:重复,位置等,来表达某类特定的字符串,进而匹配。

元字符使用

普通字符

匹配规则:每个普通字符匹配其对应的字符

In : re.findall('ab',"abcdefabcd")
Out: ['ab', 'ab'] 因为目标 字符串有两处 ab.

注意事项:正则表达式在 python 中也可以匹配中文

或关系

元字符: |

匹配规则: 匹配 | 两侧任意的正则表达式即可

In : re.findall('com|cn',"www.baidu.com/www.tmooc.cn")
Out: ['com', 'cn']
匹配单个字符

元字符: .

匹配规则:匹配除换行外的任意一 个字符,其中.可以代替任意字符.

In : re.findall('张.丰',"张三丰,张四丰,张五丰,张无忌")
Out: ['张三丰', '张四丰', '张五丰']
匹配字符集

元字符: [字符集]

匹配规则: 匹配字符集 中的任意一个字符

表达形式:
[abc#!好] 表示 [] 中的任意一 个字符
[0-9],[a-z],[A-Z] 表示 区间内的任意一 个字符
[_#?0-9a-z] 混合书写,一 般区间表达写在后面

In : re.findall('[aeiou]',"How are you!")
Out: ['o', 'a', 'e', 'o', 'u']
In [32]: re.findall('[A-Z]','Tom is not Jame')
Out[32]: ['T', 'J']
匹配字符集 反集
元字符:[^字符集]

匹配规则:匹配除了字符集以外的任意一 个字符

In : re.findall('[^0-9]',"Use 007 port")
Out: ['U', 's', 'e', ' ', ' ', 'p', 'o', 'r', 't'] #中间为空字符
匹配字符串开始位置

元字符: ^

匹配规则:匹配目标 字符串的开头位置

In : re.findall('^Jame',"Jame,hello")
Out: ['Jame']
匹配字符串的结束位置

元字符: $

匹配规则: 匹配目标 字符串的结尾位置

In : re.findall('Jame$',"Hi,Jame")
Out: ['Jame']

规则技巧: ^ 和 $必然出现在正则表达式的开头和结尾处。如果两者同时出现,则中间的部分必须匹配整个目标 字符串的全部内容。

匹配字符重复

元字符: *

匹配规则:匹配前面的字符出现 0次或多次

In : re.findall('wo*',"wooooo~~w!")
Out: ['wooooo', 'w']
In [33]: re.findall('[a-z]*','Tom is not Jam')
Out[33]: ['', 'om', '', 'is', '', 'not', '', '', 'am', '']
In [34]: re.findall('[A-Z][a-z]*','Tom is Jam')
Out[34]: ['Tom', 'Jam']

元字符:+

匹配规则: 匹配前面的字符出现 1次或多次

In : re.findall('[A-Z][a-z]+',"Hello World hello world Hello World")
Out: ['Hello', 'World', 'Hello', 'World']")

元字符:?

匹配规则: 匹配前面的字符出现 0次或 1 次

e.g. 匹配整数
In [28]: re.findall('-?[0-9]+',"Jame,age:18, -26")
Out[28]: ['18', '-26']
In [37]: re.findall('-?[0-9]',"Jame,age:18, -26")
Out[37]: ['1', '8', '-2', '6']
In [12]: re.findall('-?[0-9]+','2019?redown-15')
Out[12]: ['2019', '-15']
In [36]: re.findall('wo?','wooooo--w')
Out[36]: ['wo', 'w']

元字符:{ n}

匹配规则: 匹配前面的字符出现 n次

e.g. 匹配手机号码:因为手机号码都是 11位的,且第一 位为 1,后面 十个在 0-9中任意取.
In : re.findall('1[0-9]{n} 10}',"Jame:13886495728")
Out: ['13886495728']

元字符:{ m,n}

匹配规则: 匹配前面的字符出现 m-n次

e.g. 匹配 qq号,因为 qq都是 10,前五个在 1-9中任意取一 个,5个在 0-9 中任意取一 个
In : re.findall('[1-9][0-9]{n} 5,10}',"Baron:1259296994")
Out: ['1259296994']
匹配任意(非)数字字符

元字符: \d \D

匹配规则:\d 匹配任意数字字符,\D 匹配任意非数字字符

e.g. 匹配端口
In : re.findall('\d{1,5}',"Mysql: 3306, http:80")
Out: ['3306', '80']
In [38]: re.findall('\D{1,5}',"Mysql: 3306, http:80")
Out[38]: ['Mysql', ': ', ', htt', 'p:']
匹配任意(非)普通字符

元字符: \w \W

匹配规则: \w 匹配普通字符,\W 匹配非普通字符

说明: 普通字符指数字,字母,下划线,汉字 。

e.g. 注意'+'连接作用.
In : re.findall('\w+',"server_port = 8888")
Out: ['server_port', '8888']
In [17]: re.findall('\W+','server_port=8888')
Out[17]: ['=']
匹配任意(非)空字符

元字符: \s \S

匹配规则: \s 匹配空字符,\S 匹配非空字符

说明: 空字符指 空格 \r \n \t \v \f 字符

In : re.findall('\w+\s+\w+',"hello world")
Out: ['hello world']
In [19]: re.findall('\S+','hello world')
Out[19]: ['hello', 'world']
In [39]: re.findall('\s+','hello world')
Out[39]: [' ']
匹配开头结尾位置

元字符: \A \Z

匹配规则: \A 表示开头位置 ,\Z 表示结尾位置
In [40]: re.findall(‘\A\w+\Z’,‘Jame’)
Out[40]: [‘Jame’] 因为\w匹配普通字符,前后空字符被\A\Z匹配到了,加上连接+就是整个了.

匹配(非)单词的边界位置

元字符: \b \B

匹配规则: \b 表示单词边界,\B 表示非单词边界

说明:单词边界指数字字母(汉字)下划线与其他字符的交界位置 。

In : re.findall(r'bis\b',"This is a test.")
Out: ['is'] 因为 is去前后两端.
In [21]: re.findall('is','this is a test')
Out[21]: ['is', 'is'] 因为有两个 is.

在这里插入图片描述

正则表达式 的转义

1.如果使用正则表达式匹配特殊字符则需要加 \ 表示 转义 。
特殊字符: . * + ? ^ $ [] () {} | \

e.g. 匹配特殊字符 . 时使用 \d. 表示 本身含义
In [41]: re.findall('-?\d+\.?\d+','12 34 -1 1.56 -3.5')
Out[41]: ['12', '34', '1.56', '-3.5']
In [42]: re.findall('-?\d+\.?\d*','12 34 -1 1.56 -3.5')
Out[42]: ['12', '34', '-1', '1.56', '-3.5']
In [24]: re.findall('\$\d+','count:$100')
Out[24]: ['$100']
In [28]: re.findall('\\$\\d+','count:$100')
Out[28]: ['$100']
In [25]: re.findall('$\d+','count:$100')
Out[25]: []

2.在编程语言中,常使用原生字符串 书写正则表达式避免多重转义 的麻烦。

python 字符串 --> 正则 --> 目标 字符串
"\\$\\d+" 解析为 \$\d+ 匹配 "$100"
"\\$\\d+" 等同于 r"\$\d+"

贪婪模式 和非贪婪模式

1.定义
贪婪模式: 默认情况下,匹配重复的元字符总是尽可能多的向后匹配内容。比如: * + ? {n} m,n}
非贪婪模式(懒惰模式): 让匹配重复的元字符尽可能少的向后匹配内容。

2.贪婪模式转换为非贪婪模式

在匹配重复元字符后加 ‘?’ 号即可

​ *: *?

​ +: +?
​ ? : ??
​ {m,n} : {m,n}?

In : re.findall(r'\(.+?\)',"(abcd)efgh(higk)")
Out: ['(abcd)', '(higk)']

正则表达式 分组

1.定义
在正则表达式中,以()建立正则表达式的内部分组,子组是正则表达式的一 部分,可以作为内部整体操作对象。

2.作用

可以被作为整体操作,改变元字符的操作对象

e.g. 改变 + 号 重复的对象
In : re.search(r'(ab)+',"ababababab").group()
Out: 'ababababab'
e.g. 改变 | 号 操作对象
In : re.search(r'(王|李)\d \D w{n} 1,3}',"王者荣耀").group()
Out: '王者荣耀'

可以通过编程语言某些接口 获取匹配内容中,子组对应的内容部分

e.g. 获取 url 协议类型
In : e.search(r'(https|http|ftp|file)://\d \D S+',"https://www.baidu.com").group(1)
Out: https

3.捕获组
可以给正则表达式的子组起一 个名字,表达该子组的意义 。这种有名称的子组即为捕获组。
格式:(?P<name>pattern)

e.g. 给子组命名为 "pig"
In : re.search(r'(?P<pig>ab)+',"ababababab").group('pig')
Out: 'ab'

4.注意事项

一 个正则表达式中可以包含多个子组

子组可以嵌套,但是不要重叠或者嵌套结构复杂

子组序列号一 般从外到内,从左到右计数

在这里插入图片描述

正则表达式 匹配原则

1.正确性,能够正确的匹配出目标 字符串.

2.排他 性,除了目标 字符串之外尽可能少的匹配其他 内容.

3.全面 性,尽可能考虑到目标 字符串的所有情况,不遗漏.

Python re 模块使用

regex = compile(pattern,flags = 0)
功能: 生产正则表达式对象
参数 : pattern 正则表达式
flags 功能标 志位, 扩展正则表达式的匹配
返回值: 正则表达式对象

re.findall(pattern,string,flags = 0)
功能: 根据正则表达式匹配目标 字符串内容
参数 : pattern 正则表达式
string 目标 字符串
flags 功能标 志位, 扩展正则表达式的匹配
返回值: 匹配到的内容列表, 如果正则表达式有子组则只能获取到子组对应的内容

regex.findall(string,pos,endpos)
功能: 根据正则表达式匹配目标 字符串内容
参数 : string 目标 字符串
pos 截取目标 字符串的开始匹配位置
endpos 截取目标 字符串的结束匹配位置
返回值: 匹配到的内容列表, 如果正则表达式有子组则只能获取到子组对应的内容

re.split(pattern,string,flags = 0)
功能: 使用正则表达式匹配内容, 切割目标 字符串
参数 : pattern 正则表达式
string 目标 字符串
flags 功能标 志位, 扩展正则表达式的匹配
返回值: 切割后的内容列表

re.sub(pattern,replace,string,max,flags = 0)
功能: 使用一 个字符串替换正则表达式匹配到的内容
参数 : pattern 正则表达式
replace 替换的字符串
string 目标 字符串
max 最多替换几处, 默认替换全部
flags 功能标 志位, 扩展正则表达式的匹配
返回值: 替换后的字符串

re.subn(pattern,replace,string,max,flags = 0)
功能: 使用一 个字符串替换正则表达式匹配到的内容
参数 : pattern 正则表达式
replace 替换的字符串
string 目标 字符串
max 最多替换几处, 默认替换全部
flags 功能标 志位, 扩展正则表达式的匹配
返回值: 替换后的字符串和替换了几处

import re
s = 'alex:1995,sunny:1991'
# 使用正则表达式匹配内容 , 切割目标字符串
l = re.split(r'[,:]',s)
print(l) #['alex', '1995', 'sunny', '1991']
# 使用一个字符串替换正则表达式匹配到的内容
# s = re.sub(r':','-',s,1)
# print(s) #alex-1995,sunny:1991
# 使用一个字符串替换正则表达式匹配到的内容
s = re.subn(r':','-',s,1)
print(s) #('alex-1995,sunny:1991', 1)

re.finditer(pattern,string,flags = 0)
功能: 根据正则表达式匹配目标 字符串内容
参数 : pattern 正则表达式
string 目标 字符串
flags 功能标 志位, 扩展正则表达式的匹配
返回值: 匹配结果的迭代器

import re
s = ' 今年是 2019 年 , 建国 70 周年 '
pattern = r'\d+' 匹配所有数字
item = re.finditer(pattern,s)
for i in item:
	print(i.group()) #2019 70

re.fullmatch(pattern,string,flags=0)
功能:完全匹配某个目标 字符串
参数 :pattern 正则
string 目标 字符串
返回值:匹配内容 match object

import re
s = " 今年是 2019 年 , 建国 70 周年 "
# 完全匹配
obj = re.fullmatch(r'.+',s)
print(obj.group())# 今年是 2019 年 , 建国 70 周年

re.match(pattern,string,flags=0)
功能:匹配某个目标 字符串开始位置
参数 :pattern 正则
string 目标 字符串
返回值:匹配内容 match object

import re
s = " 今年是 2019 年 , 建国 70 周年 "
# 匹配开始位置
obj = re.match(r'\w+',s)
print(obj.group()) # 今年是 2019 年

re.search(pattern,string,flags=0)
功能:匹配目标 字符串第一 个符合内容
参数 :pattern 正则
string 目标 字符串
返回值:匹配内容 match object

import re
s = " 今年是 2019 年 , 建国 70 周年 "
# 匹配第一处
obj = re.search(r'\d+',s)
print(obj.group()) #2019

compile 对象属性
【1 】 pattern : 正则表达式
【2 】 groups : 子组数 量
【3 】 groupindex : 捕获组名与组序号的字典

import re
#1.匹配一个.com邮箱格式的邮箱
print(re.findall(r'\w+@\w+\.com','zhiqiang@669.com'))
#结果:['zhiqiang@669.com']

#2.匹配一个密码8-12位,数字字母下划线构成
print(re.findall(r'\w{8,12}','zhiq14521'))
#结果:['zhiq14521']

#3.匹配一个数字,包含整数,小数,正数,负数,分数1/2及百分数4.6%
print(re.findall(r'-?\d+\.?/?\d*%?','1 -21 12.5 -12.8 0 1/3 4.6% '))
#结果:['1', '-21', '12.5', '-12.8', '0', '1/3', '4.6%']

#4.匹配一段文字中以大写字母开头的单词,注意文字中可能含有ipython这种,不算大写字母开头,H-base这种算大写字母开头,BSD也是.
print(re.findall(r'\b[A-Z][-_a-zA-Z]*','Hello iPython H-base BSD'))
#结果:['Hello', 'H-base', 'BSD']

#每个普通字符匹配其对应的字符,此处ab有两处,则结果也是两处
print(re.findall('ab','abcdefabcd'))
#结果:['ab', 'ab']

#匹配'|'或,两侧任意的正则表达式即可
print(re.findall('com|cn','www.baidu.com/www.twoo.cn'))
#结果:['com', 'cn']

#匹配除换行外的任意一个字符,其中.可以代替任意字符
print(re.findall('张.丰','张三丰,张无忌,张四丰'))
#结果:['张三丰', '张四丰']

#匹配字符集中的任意一个字符
print(re.findall('[aeiou]','how are you'))
#结果:['o', 'a', 'e', 'o', 'u']
print(re.findall('[A-Z]','Tom is Jam' ))
#结果:['T', 'J']

#匹配除了字符集以外的任意一个字符
print(re.findall('[^0-9]','use 007 port'))
#结果:['u', 's', 'e', ' ', ' ', 'p', 'o', 'r', 't']

#匹配目标字符串的开头位置
print(re.findall('^tom','tom is jame'))
#结果:['tom']

#匹配目标字符串的结尾位置
print(re.findall('tom$','jame is tom'))
#结果:['tom']

#匹配前面的字符出现0次或多次
print(re.findall('wo*','wooooooooooo--w!'))
#结果:['wooooooooooo', 'w']
print(re.findall('[a-z]*','Tom is not Jam'))
#结果:['', 'om', '', 'is', '', 'not', '', '', 'am', '']
print(re.findall('[A-Z][a-z]*','Tom is Jam'))
#结果:['Tom', 'Jam']

#匹配前面的字符出现1次或多次
print(re.findall('[A-Z][a-z]+',"Hello World  hello world  Hello World"))
#结果:['Hello', 'World', 'Hello', 'World']

#匹配前面的字符出现0次或1次
print(re.findall('-?[0-9]+',"Jame,age:18, -26"))
#结果:['18', '-26']
print(re.findall('[0-9]?',"Jame,age:18, -26"))
#结果:['', '', '', '', '', '', '', '', '', '1', '8', '', '', '', '2', '6', '']
print(re.findall('-?[0-9]',"Jame,age:18, -26"))
#结果:['1', '8', '-2', '6']
print(re.findall('-?[0-9]+','2019?redown-15'))
#结果:['2019', '-15']
print(re.findall('wo?','wooooo--w'))
#结果:['wo', 'w']

#匹配前面的字符出现n次,因为手机号码都是11位的,且第一位为1,后面十个在0-9中任意取.
print(re.findall('1[0-9]{10}',"Jame:13886495728"))
#结果:['13886495728']

#匹配前面的字符出现m-n次,因为qq都是10位,前五个在1-9中任意取一个,后5个在0-9中任意取一个
print(re.findall('[1-9][0-9]{5,10}',"Baron:1259296994"))
#结果:['1259296994']

# \d 匹配任意数字字符 \D 匹配任意非数字字符
print(re.findall('\d{1,5}',"Mysql: 3306, http:80"))
#结果:['3306', '80']
print(re.findall('\D{1,5}',"Mysql: 3306, http:80"))
#结果:['Mysql', ': ', ', htt', 'p:']

#\w 匹配普通字符,\W 匹配非普通字符
print(re.findall('\w+',"server_port = 8888"))
#结果:['server_port', '8888']
print(re.findall('\W+','server_port=8888'))
#结果:['=']

#\s 匹配空字符,\S 匹配非空字符
print(re.findall('\S+','hello  world'))
#结果:['hello', 'world']
print(re.findall('\s+','hello  world'))
#结果:['  ']
print(re.findall('\w+\s+\w+','hello world'))
#结果:['hello world']

#\A 表示开头位置,\Z 表示结尾位置,因为\w匹配普通字符,前后空字符被\A\Z匹配到了,加上连接+就是整个了.
print(re.findall('\A\w+\Z','Jame'))
#结果:['Jame']
print(re.findall('\A','Jame'))
#结果:['']
print(re.findall('\Z','Jame'))
#结果:['']

#\b 表示单词边界,\B 表示非单词边界
print(re.findall(r'\bis\b',"This is a test."))#is去除前后两端
#结果:['is']
print(re.findall('is','this is a test'))#两个is
#结果:['is', 'is']

print(re.findall(r'a*','abcdefg'))
#结果:['a', '', '', '', '', '', '', '']
print(re.findall('a*','abcdefg'))
#结果:['a', '', '', '', '', '', '', '']
print(re.findall(r'a+','abcdefg'))
#结果:['a']
print(re.findall('a+','abcdefg'))
#结果:['a']

print(re.findall('-?\d+\.?\d+','12 34 -1 1.56 -3.5'))
#结果:['12', '34', '1.56', '-3.5']
print(re.findall('-?\d+\.?\d*','12 34 -1 1.56 -3.5'))
#结果:['12', '34', '-1', '1.56', '-3.5']

print(re.findall('\$\d+','count:$100'))
#结果:['$100']
print(re.findall('$\d+','count:$100'))
#结果:[]
print(re.findall('\\$\\d+','count:$100'))
#结果:['$100']

print(re.findall(r'\(.+?\)',"(abcd)efgh(higk)"))
#结果:['(abcd)', '(higk)']
print(re.findall(r'\(.+\)',"(abcd)efgh(higk)"))
#结果:['(abcd)efgh(higk)']
print(re.findall(r'ab+','abababababab'))
#结果:['ab', 'ab', 'ab', 'ab', 'ab', 'ab']

print(re.search(r'(ab)+','abababab').group())
#结果:abababab
print(re.search(r'王|李\w{1,3}','王者荣耀').group())
#结果:王
print(re.search(r'王|李\w{1,3}','李世民').group())
#结果:李世民
print(re.search(r'(王|李)\w{1,3}','王者荣耀').group())
#结果:王者荣耀

print(re.search(r'(https|http|ftp|file)://\S+',"https://www.baidu.com").group(1))
#结果:https

print(re.search(r'(?P<name>ab)+','ababababab').group('name'))
#结果:ab

print(re.search(r'\d+','360733199102200512').group())
#结果:360733199102200512
print(re.search(r'\d{18}','360733199102200512').group())
#结果:360733199102200512
print(re.search(r'\d{17}(\d|x)','36073319910220051x').group())
#结果:36073319910220051x

print(re.findall(r'(\w+):(\d+)','alex:1995,sunny:1991'))
#结果:[('alex', '1995'), ('sunny', '1991')]

match 对象的属性方法

1.属性变量

pos 匹配的目标 字符串开始位置

endpos 匹配的目标 字符串结束位置

re 正则表达式

string 目标 字符串

lastgroup 最后一 组的名称

lastindex 最后一 组的序号

2.属性方法

span() 获取匹配内容的起止位置

start() 获取匹配内容的开始位置

end() 获取匹配内容的结束位置

groupdict() 获取捕获组字典 ,组名为键,对应内容为值

groups() 获取子组对应内容

group(n = 0)
功能:获取 match 对象匹配内容
参数 :默认为 0表示 获取整个 match 对象内容,如果是序列号或者组名则表示 获取对应子组内容
返回值:匹配字符串

在这里插入图片描述

import re
pattern = r'(ab)cd(?P<name>ef)'
regex = re.compile(pattern)
info = regex.search('abcdefghi')#match 对象
# 属性变量
print(info.pos) #0
print(info.endpos) #9
print(info.re)#re.compile('(ab)cd(?P<name>ef)')
print(info.string) #abcdefghi
print(info.lastgroup)#name
print(info.lastindex)#2
print('----------')
# 属性方法
print(info.span()) #(0, 6)
print(info.start()) #0
print(info.end()) #6
print(info.groups()) #('ab', 'ef')
print(info.groupdict()) #{'name': 'ef'}
print(info.group()) #abcdef
print(info.group('name')) #ef

flags 参数扩展

1.使用函数 :re模块调用的匹配函数 。如:re.compile,re.findall,re.search…

2.作用:扩展丰富正则表达式的匹配功能

3.常用 flag

> A == ASCII 元字符只能匹配 ascii> I == IGNORECASE 匹配忽略字母大小写
> S == DOTALL 使 . 可以匹配换行
> M == MULTILINE 使 ^ $可以匹配每一行的开头结尾位置

4.使用多个 flag
方法 :使用按位或连接

e.g. : flags = re.I | re.A
正则表达式示例
#clear_unusual.py:清理掉没有内容或者乱码的txt文档的程序
import re
s = '''Hello
北京 '''
regex = re.compile(r'\w',flags=re.A)
# 只能匹配 ascii 码 ['H', 'e', 'l', 'l', 'o']
regex = re.compile(r'[a-z]+',flags=re.I)
# 匹配忽略字母大小写 ['Hello']
regex = re.compile(r'.+') #['Hello', ' 北京 ']
regex = re.compile(r'.+',flags= re.S)
# 使 . 可以匹配换行 #['Hello\n 北京 ']
regex = re.compile(r'^ 北京 ') #[]
regex = re.compile(r'^ 北京 ',flags=re.M)
#[' 北京 ']
# 使 ^ $ 可以匹配每一行的开头结尾位置
regex = re.compile(r'Hello$') #[]
regex = re.compile(r'Hello$',flags=re.M)
#['Hello']
l = regex.findall(s)
print(l)
import re
def get_address(port):
    f = open('exc.txt', 'r')
    while True:#获取段落
        data = ''
        for line in f:
            if line == '\n':
                break
            data += line
        if not data:#文件已经结束
            break
        info = re.match(port,data)#判断是不是想要的段落
        if info:#如果info不是None说明找到目标段落
            print(data)
            # pattern = r'[0-9a-f]{4}\.[0-9a-f]{4}\.[0-9a-f]{4}'
            pattern = r'([0-9]{1,3}\.){3}[0-9]{1,3}/\d+|Unknow'
            address = re.search(pattern,data).group()
            return address

if __name__=='__main__':
    port = input('端口:')
    print(get_address(port))

文献解析示例

#文献解析第一步#clear_unusual.py:清理掉没有内容或者乱码的txt文档的程序
import os
import codecs
import pickle
import re
import json
from time import *

path = '//10.132.20.100/nlpdata/all/100100'

def scan_txt():
    '''
    遍历指定文件夹,显示文件夹所有文件名
    :return:
    '''
    file_list = []
    for root, dirs, files in os.walk(path):
        for file in files:
            if os.path.splitext(file)[1] == '.txt':
                file_list.append(os.path.join(root, file))
    return file_list

def process_txt(lines_list):
    '''
    循环清理掉所有乱码及扫描档文献
    :param lines_list:
    :return:
    '''
    cleat_list = []
    for line1 in lines_list:
        # print(line1)
        new_line = line1.strip()
        print(len(new_line))
        if re.search('^一、', new_line) or re.search('^二、', new_line) or re.search('\d%$', new_line) \
                or re.search('[*?+#&^@$]', new_line) or re.search('^(\d)', new_line) or re.search('(\d)$', new_line) \
                or re.search('.jpg', new_line) or re.search('\d$', new_line) or re.search('^\d', new_line) \
                or re.search('http', new_line) or re.search('www', new_line) or re.search('---*', new_line):
            continue
        else:
            cleat_list.append(new_line)
    return cleat_list

def main():
    '''
    清除所有以.pdf和.pdfbox.txt结尾的重复txt文件及清除所有扫描档文件并将其文件名保存再yichang01.txt文档中
    :return: 正常有数据的文件名保存在file01.txt文档中以便下次调用
    '''
    begin_time = time()
    file_list = scan_txt()
    print(file_list)
    print(len(file_list))
    for filename in file_list:
        if filename.endswith('.pdf.pdfbox.txt'):
            print(filename)
            with open('D:/liu/yichang01.txt', 'a+', encoding='utf-8') as f1:
                f1.write(filename + '\n')
        else:
            file1 = filename
            title_dict = {}
            lines_list = []
            with open(file1, 'r', encoding='utf-8', errors='replace') as f:
                for i in range(30):
                    lines = f.readline().strip()
                    lines_list.append(lines)
            print(lines_list)
            clear_list = process_txt(lines_list)
            print(clear_list)
            lines_str = ''.join(clear_list)
            title_dict[filename] = lines_str
            print(title_dict)
            for key in title_dict:
                if title_dict[key] == '':
                    with open('D:/liu/yichang01.txt', 'a+', encoding='utf-8') as f1:
                        f1.write(key + '\n')
                else:
                    with open('D:/liu/file01.txt', 'a+', encoding='utf-8') as f2:
                        f2.write(key + '\n')
    end_time = time()
    run_time = end_time - begin_time
    print('耗时:', run_time)

if __name__ == '__main__':
    main()
#文献解析第二步:title_recognition.py:识别出标题的程序。
import os
import codecs
import pickle
import re
import json
import csv
from time import *

path = '//10.132.20.100/nlpdata/all/100100'


def scan_txt():
    '''
    遍历指定文件夹,显示文件夹所有文件名
    :return:
    '''
    file_list = []
    for root, dirs, files in os.walk(path):
        for file in files:
            if os.path.splitext(file)[1] == '.txt':
                file_list.append(os.path.join(root, file))
    return file_list


def get_info(lines_list):
    '''
    循环迭代处理所有文件,返回每个文件前三十行的内容
    :param lines_list:
    :return:
    '''
    info_list = []
    for line in lines_list:
        new_line = line.strip()
        info_list.append(new_line)
    print(info_list)
    info_str = '***'.join(info_list)
    return info_str


def recognize_eng(info_dict):
    '''
    将中英文文献区分开,中文文献路径存在一个列表中,英文文献路径存入另一个列表中
    :param info_dict:
    :return:
    '''
    eng_dict = {}
    eng_list = []
    for key, value in info_dict.items():
        value2 = value.split('***')
        for value3 in value2:
            if re.search('[A-Za-z0-9]+', value3):
                lines = value3
                eng_list.append(lines)
                eng_dict[key] = eng_list
    return eng_dict


def process_txt(lines_list):
    '''
    循环清理掉所有文献的证券代码,公告编号
    :param lines_list:
    :return:
    '''
    clear_list = []
    for line1 in lines_list:
        new_line = line1
        if re.search('证券代码', new_line) or re.search('股票代码', new_line) or re.search('Stock ID', new_line) \
                or re.search('邮.*编', new_line) or re.search('Tel', new_line) or re.search('.*街.*号.*楼', new_line) \
                or re.search('^一、', new_line) or re.search('^二、', new_line) or re.search('^\d.*\d$', new_line) \
                or re.search('第.*页', new_line) or re.search('[*?+#&^@$]', new_line) or re.search('\dF', new_line):
            continue
        else:
            clear_list.append(new_line)
            if re.search('报.*告', new_line) or re.search('公.*告', new_line) or re.search('通.*知', new_line) \
                    or re.search('Notes', new_line) or re.search('Sheet', new_line) or re.search('Statement', new_line):
                break
    return clear_list


def process_txt2(lines_list2):
    '''
    循环清理掉所有文献的证券代码,公告编号
    :param lines_list2:
    :return:
    '''
    clear_list2 = []
    for line1 in lines_list2:
        new_line = line1
        if re.search('证券代码', new_line) or re.search('股票代码', new_line) or re.search('Stock ID', new_line) \
                or re.search('邮.*编', new_line) or re.search('Tel', new_line) or re.search('.*街.*号.*楼', new_line) \
                or re.search('^一、', new_line) or re.search('^二、', new_line) or re.search('^\d.*\d$', new_line) \
                or re.search('第.*页', new_line) or re.search('[*?+#&^@$]', new_line) or re.search('\dF', new_line):
            continue
        else:
            clear_list2.append(new_line)
            if re.search('报.*告', new_line) or re.search('公.*告', new_line) or re.search('通.*知', new_line) \
                    or re.search('Notes', new_line) or re.search('Sheet', new_line) or re.search('Statement', new_line):
                break
    return clear_list2


def recognize_title(clear_list):
    '''
    循环筛选出所有文献的标题
    :param clear_list:
    :return:
    '''
    title_list = []
    for line1 in clear_list:
        line2 = line1.strip()
        if not re.search('[,:。、!√]', line2) and not re.search('序.*号', line2) and not re.search('页.*次', line2):
            title_list.append(line2)
        else:
            break
    print(title_list)
    title_set = sorted(set(title_list), key=title_list.index)
    title_str = ''.join(title_set)
    print(title_str)


def recognize_title2(clear_list2):
    '''
    循环筛选出所有文献的标题
    :param clear_list:
    :return:
    '''
    title_list = []
    for line1 in clear_list2:
        line2 = line1.strip()
        if not re.search('[,:.!√]', line2) and not re.search('序.*号', line2) and not re.search('页.*次', line2):
            title_list.append(line2)
        else:
            break
    print(title_list)
    title_set = sorted(set(title_list), key=title_list.index)
    title_str = ''.join(title_set)
    print(title_str)


def remove_blank(title_dict):
    '''
    循环删除所有文献标题的空格
    :param title_dict:
    :return:
    '''
    clear_title_dict = {}
    lines_list = []
    for key, value in title_dict.items():
        if re.search('[A-Za-z0-9]+', value):
            lines = value
        else:
            lines = ''.join(value.split())
        lines_list.append(lines)
        title_set = sorted(set(lines_list), key=lines_list.index)
        clear_title = ''.join(title_set)
        clear_title_dict[key] = clear_title
    return clear_title_dict


def make_tag(clear_title_dict):
    '''
    循环按规则给所有文件的标题打上标签
    :param clear_title_dict:
    :return:
    '''
    key_list = []
    label_list = []
    for key, value in clear_title_dict.items():
        key_list.append(key)
        if re.search('公告', value) or re.search('Announcement', value) or re.search('announcement', value):
            label = '公告'
        elif re.search('章程', value) or re.search('ARTICLES', value):
            label = '章程'
        elif re.search('报告', value) or re.search('快报', value) or re.search('Report', value):
            label = '报告'
        elif re.search('办法', value):
            label = '办法'
        else:
            label = 'None'
        label_list.append(label)
    return label_list


def output_tag(clear_title_dict, label_list):
    '''
    输出文件路径,标签,以便后续查找出无标签的情况
    :param clear_title_dict:
    :param label_list:
    :return:
    '''
    key_list = []
    label_dict = {}
    for key in clear_title_dict:
        key_list.append(key)
    for filename, label in zip(key_list, label_list):
        label_dict[filename] = label
    return label_dict


def output_json(clear_title_dict, label_list):
    '''
    输出最后结果,含文献路径,标题,标签
    :param clear_title_dict:
    :param label_list:
    :return:
    '''
    key_list = []
    value_list = []
    result = {}
    for key, value in clear_title_dict.items():
        key_list.append(key)
        value_list.append(value)
    for filename, Title, label in zip(key_list, value_list, label_list):
        result[filename] = {Title: label}
    return result


def output_data(clear_title_dict, label_list):
    '''
    输出最后结果,含文献路径,标题,标签
    :param clear_title_dict:
    :param label_list:
    :return:
    '''
    key_list = []
    value_list = []
    for key, value in clear_title_dict.items():
        key_list.append(key)
        value_list.append(value)
    for filename, Title, label in zip(key_list, value_list, label_list):
        consequence = {
            'payload': {
                'result': {
                    'data': [{
                        'fileID': filename,
                        'title': Title,
                        'label': label
                    }],
                    'totalCount': 1
                },
                'success': 'true'
            },
        }
        return consequence


def output_info(clear_title_dict, label_list, info_dict):
    '''
    输出最后结果:含文献路径,文献内容,标题,标签
    :param clear_title_dict:
    :param label_list:
    :param info_dict:
    :return:
    '''
    key_list = []
    value_list = []
    content_list = []
    show_dict = {}
    for key, value in clear_title_dict.items():
        key_list.append(key)
        value_list.append(value)
    for content in info_dict.values():
        content_list.append(content)
    for filename, info, Title, label in zip(key_list, content_list, value_list, label_list):
        show_dict[filename] = {info: {Title: label}}
    return show_dict


def main():
    '''
    清除所有以.pdf和.pdfbox.txt结尾的重复txt文件及清除所有扫描档文件并将其文件名保存再yichang01.txt文档中
    :return: 正常有数据的文件名保存在file01.txt文档中以便下次调用
    '''
    begin_time = time()
    file_list = scan_txt()
    with open('test01.csv', 'a+', newline='', encoding='utf-8') as f7:
        writer = csv.writer(f7, dialect='excel')
        header = ['文件名', '标题候选文本', '文本标题', '文本类型']
        writer.writerow(header)
    with open('D:/liu/file01.txt', 'r', encoding='utf-8') as f1:
        data_list = f1.readlines()
        for data in data_list:
            data1 = data.strip('\n')
            title_dict = {}
            info_dict = {}
            lines_list = []
            lines_list2 = []
            with open(data1, 'r', encoding='utf-8', errors='replace') as f:
                for i in range(30):
                    lines = f.readline()
                    lines_list.append(lines)
            print(data1)
            print(lines_list)
            info_str = get_info(lines_list)
            info_dict[data1] = info_str
            print(info_dict)
            eng_dict = recognize_eng(info_dict)
            print(eng_dict)
            clear_list = process_txt(lines_list)
            print(clear_list)
            title_str = recognize_title(clear_list)
            title_dict[data1] = title_str
            print(title_dict)
            for key1 in title_dict:
                if title_dict[key1] == '':
                    with open(key1, encoding='utf-8', errors='replace') as f1:
                        for i in range(30):
                            lines2 = f1.readline().strip()
                            lines_list2.append(lines2)
                    clear_list2 = process_txt2(lines_list2)
                    title_str02 = recognize_title2(clear_list2)
                    title_dict[key1] = title_str02
            print(title_dict)
            for key2 in title_dict:
                if title_dict[key2] == '':
                    with open('D://liu/file60.txt', 'a+', encoding='utf-8') as f2:
                        f2.write(key2 + '\n')
            for key in list(title_dict.keys()):
                if not title_dict.get(key):
                    del title_dict[key]
            clear_title_dict = remove_blank(title_dict)
            label_list = make_tag(clear_title_dict)
            label_dict = output_tag(clear_title_dict, label_list)
            print(label_dict)
            for key3 in label_dict:
                if label_dict[key3] == 'None':
                    with open('D:/liu/file70.txt', 'a+', encoding='utf-8') as f8:
                        f8.write(key3 + '\n')
            result = output_json(clear_title_dict, label_list)
            consequence = output_data(clear_title_dict, label_list)
            print(consequence)
            print(type(consequence))
            print(result)
            result_json = json.dumps(result, ensure_ascii=False)
            consequence_json = json.dumps(consequence, ensure_ascii=False, indent=4)
            with open('D:/liu/test01.json', 'a+', encoding='utf-8') as f3:
                f3.write(result_json + '\n')
            with open('D:/liu/test01.txt', 'a+', encoding='utf-8') as f4:
                f4.write(result_json + '\n')
            with open('D:/liu/test10.json', 'a+', encoding='utf-8') as f5:
                f5.write(consequence_json + '\n')
            with open('D:/liu/test10.txt', 'a+', encoding='utf-8') as f6:
                f6.write(consequence_json + '\n')
            show_dict = output_info(clear_title_dict, label_list, info_dict)
            print(show_dict)
            with open('test01.csv', 'a+', newline='', encoding='utf-8') as f7:
                writer = csv.writer(f7, dialect='excel')
                for key10, value10 in show_dict.items():
                    for key20, value20 in value10.items():
                        for key30, value30 in value20.items():
                            writer.writerow([key10, key20, key30, value30])

    end_time = time()
    run_time = end_time - begin_time
    print('耗时:', run_time)


if __name__ == '__main__':
    main()

st):
consequence = {
‘payload’: {
‘result’: {
‘data’: [{
‘fileID’: filename,
‘title’: Title,
‘label’: label
}],
‘totalCount’: 1
},
‘success’: ‘true’
},
}
return consequence

def output_info(clear_title_dict, label_list, info_dict):
‘’’
输出最后结果:含文献路径,文献内容,标题,标签
:param clear_title_dict:
:param label_list:
:param info_dict:
:return:
‘’’
key_list = []
value_list = []
content_list = []
show_dict = {}
for key, value in clear_title_dict.items():
key_list.append(key)
value_list.append(value)
for content in info_dict.values():
content_list.append(content)
for filename, info, Title, label in zip(key_list, content_list, value_list, label_list):
show_dict[filename] = {info: {Title: label}}
return show_dict

def main():
‘’’
清除所有以.pdf和.pdfbox.txt结尾的重复txt文件及清除所有扫描档文件并将其文件名保存再yichang01.txt文档中
:return: 正常有数据的文件名保存在file01.txt文档中以便下次调用
‘’’
begin_time = time()
file_list = scan_txt()
with open(‘test01.csv’, ‘a+’, newline=‘’, encoding=‘utf-8’) as f7:
writer = csv.writer(f7, dialect=‘excel’)
header = [‘文件名’, ‘标题候选文本’, ‘文本标题’, ‘文本类型’]
writer.writerow(header)
with open(‘D:/liu/file01.txt’, ‘r’, encoding=‘utf-8’) as f1:
data_list = f1.readlines()
for data in data_list:
data1 = data.strip(‘\n’)
title_dict = {}
info_dict = {}
lines_list = []
lines_list2 = []
with open(data1, ‘r’, encoding=‘utf-8’, errors=‘replace’) as f:
for i in range(30):
lines = f.readline()
lines_list.append(lines)
print(data1)
print(lines_list)
info_str = get_info(lines_list)
info_dict[data1] = info_str
print(info_dict)
eng_dict = recognize_eng(info_dict)
print(eng_dict)
clear_list = process_txt(lines_list)
print(clear_list)
title_str = recognize_title(clear_list)
title_dict[data1] = title_str
print(title_dict)
for key1 in title_dict:
if title_dict[key1] == ‘’:
with open(key1, encoding=‘utf-8’, errors=‘replace’) as f1:
for i in range(30):
lines2 = f1.readline().strip()
lines_list2.append(lines2)
clear_list2 = process_txt2(lines_list2)
title_str02 = recognize_title2(clear_list2)
title_dict[key1] = title_str02
print(title_dict)
for key2 in title_dict:
if title_dict[key2] == ‘’:
with open(‘D://liu/file60.txt’, ‘a+’, encoding=‘utf-8’) as f2:
f2.write(key2 + ‘\n’)
for key in list(title_dict.keys()):
if not title_dict.get(key):
del title_dict[key]
clear_title_dict = remove_blank(title_dict)
label_list = make_tag(clear_title_dict)
label_dict = output_tag(clear_title_dict, label_list)
print(label_dict)
for key3 in label_dict:
if label_dict[key3] == ‘None’:
with open(‘D:/liu/file70.txt’, ‘a+’, encoding=‘utf-8’) as f8:
f8.write(key3 + ‘\n’)
result = output_json(clear_title_dict, label_list)
consequence = output_data(clear_title_dict, label_list)
print(consequence)
print(type(consequence))
print(result)
result_json = json.dumps(result, ensure_ascii=False)
consequence_json = json.dumps(consequence, ensure_ascii=False, indent=4)
with open(‘D:/liu/test01.json’, ‘a+’, encoding=‘utf-8’) as f3:
f3.write(result_json + ‘\n’)
with open(‘D:/liu/test01.txt’, ‘a+’, encoding=‘utf-8’) as f4:
f4.write(result_json + ‘\n’)
with open(‘D:/liu/test10.json’, ‘a+’, encoding=‘utf-8’) as f5:
f5.write(consequence_json + ‘\n’)
with open(‘D:/liu/test10.txt’, ‘a+’, encoding=‘utf-8’) as f6:
f6.write(consequence_json + ‘\n’)
show_dict = output_info(clear_title_dict, label_list, info_dict)
print(show_dict)
with open(‘test01.csv’, ‘a+’, newline=‘’, encoding=‘utf-8’) as f7:
writer = csv.writer(f7, dialect=‘excel’)
for key10, value10 in show_dict.items():
for key20, value20 in value10.items():
for key30, value30 in value20.items():
writer.writerow([key10, key20, key30, value30])

end_time = time()
run_time = end_time - begin_time
print('耗时:', run_time)

if name == ‘main’:
main()


















































  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值