基础语法

字面量

​ 概述:在代码中,被写下来的的固定的值称之为字面量。

​ 常见的值类型:数字(Number),字符串(String),列表(List),元组(Tuple),集合(Set),字典(Dictionary)

注释

​ 单行注释:如 # 这是一段注释

​ 多行注释:以一对三个双引号或者单引号引起来(“””注释内容”””)

变量

​ 概述:在程序运行时,能储存计算结果或能表示值的抽象概念。

​ 简单的说,变量就是在程序运行时,记录数据用的。

​ python中变量是没有类型的,但是变量中存储的数据是有类型的。

数据类型

​ string,float,int,complex

​ 验证数据类型:type()方法

String字符串

​ 定义:

​ ①单引号定义法:name = ‘ 黑马程序员’

​ ②双引号定义法:name = “黑马程序员”

​ ③三引号定义法:name = “””黑马程序员”””

​ 注意:

​ ①嵌套时,单双引号要交叉使用。或者使用\转义字符

​ 字符串的拼接

​ 可以直接通过 + 进行拼接

​ 但整数和字符串拼接需要用到格式化

​ 字符串的格式化

​ %s,%d,%f

​ %是占位符,s表示将变量以字符串的形式放进去,d是以整数,f是以浮点数。

​ 如"pringt("我考了%s" % score)就表示将score变量放到%s那里。

​ 还有一种使用f和 {}的搭配进行格式化的,但不管精度控制,仅仅快捷方便如下所示。

​ 如pringt(f"我考了{score}")

​ 精度控制

​ 可以采用辅助符合m.n开控制数据的宽度和精度。

​ m:控制宽度,要求是数字(很少使用) ,设置的宽度小于数字自身,不生效。

​ .n:控制小数点精度,要求是数字,会进行小数的四舍五入。

​ 如%5.2f:表示将宽度控制为5(小数点也算一位),将小数点精度设置为2。

数据类型转换

​ int():强制将int、float、bool、纯数字字符串转为int

​ float():强制将int、float、bool、纯数字字符串转为float

​ str():转字符串

​ complex():强制将int、float、bool、纯数字字符串、complex转为complex

注意:

​ ①想要将字符串转换成数字,必须要求字符串内的内容都是数字。

​ ②当两个不同类型的数据进行运算的时候,低精度默认向高精度转换。bool -> int -> float -> complex

​ ③不要用小数作比较,存在精度损耗

标识符

​ 概述:是用户在编程的时候所使用的一系列名字,用于给变量、类、方法等命名。

​ 规则:

​ ①内容限定。只允许英文,中文,数字,下划线。数字不能开头。

​ ②大小写敏感。

​ ③不可使用关键字。

​ 注意:

​ ①推荐下划线命名法,英文字母建议小写。

运算符

​ 算数运算符

​ 赋值运算符

键盘输入

​ input函数

​ 注意:

​ ①他返回的是字符串。可以在input参数内写入提示语句,会先输出提示语句再从键盘录入

判断语句

if

​ 格式:

​ if 要判断的条件:

​ 条件成立时要做的事情

循环语句

for

​ 本质:相当于一种轮询的机制,是对序列类型的内容进行逐个处理。

​ 格式:

​ for 变量 in 被处理的数据:

​ 循环满足时执行的代码

range

​ range(num):表示获取一个从0到num,但不包含num的数字序列。

​ range(num,num1):获取一个从num到num1但不包含num1的数字序列。

​ range(num,num1,step):获取从num到num1但不包含num1,且步长为step的数字序列

while

​ 本质:他的循环条件是自定义的,自行控制循环条件。

循环中断

break

​ 作用:直接结束该循环。

continue

​ 作用:中断本次循环,进入下一次循环

函数

​ 定义格式:

​ def 函数名(参数):

​ 函数体

​ return 返回值

​ 无返回值实际是返回了None这个字面量。同时在定义一个函数时尽量注释清楚函数作用和参数和返回值。

函数的多返回值

​ 通过return返回多个值,中间用逗号隔开,可以以多个变量进行接收。以元组的形式返回。

函数的多种传参方式

​ 位置参数:调用函数时根据函数定义的参数位置来传递参数

​ 关键字参数:函数调用时通过“键=值”的形式传递参数.

​ 注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。

​ 缺省参数:即默认参数,为参数设置默认值

​ 注意:所有位置参数必须出现在默认参数前,包括函数定义和调用。

​ 不定长参数:即可变参数,用于不确定要传入多少个参数的场景,而他又分为位置传递和关键字传递两种类型。

​ 位置传递不定长

​ 概述:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是位
置传递。

​ 使用:在参数位置定义为*args

​ 关键字传递不定长

​ 使用:在参数位置定义为**kwargs

​ 注意:参数是“键=值”形式的形式的情况下,所有的“键=值”都会被kwargs接受,同时会根据“键=值”组成字典.

匿名函数

​ 概述:函数本身也可以作为参数传入,它可以理解为计算逻辑的传递,而不是数据的传递

lambda函数

​ 场景:可以定义一个无名称的匿名函数,只可临时使用一次

​ 定义语法:lambda 传入参数:函数体(一行代码)

1
2
3
4
5
解释:
其中lambda是关键字,表示定义匿名函数.
传入参数表示匿名函数的形式参数,如: x, y表示接收2个形式参数
函数体,就是函数的执行逻辑,要注意:只能写一行,无法写多行代码
默认返回的就是函数体的执行结果

数据容器

list列表

​ 定义方式一:获取列表的字面量

1
2
#字面量
[元素1,元素2....]

​ 定义方式二:获取列表的变量

1
2
#定义变量
变量名称 = [元素1,元素2....]

​ 定义方式三:获取一个空列表

1
2
3
#定义空列表
变量名称 = []
变量名称 = list()

嵌套列表:也就是多维列表

​ 列表的下标索引

​ 语法:列表名称[索引]

​ 从前往后是从0开始。

​ 从后往前是从-1开始往后依次-2,-3等

​ 列表的方法

​ ①list.index(元素值):根据元素值去查找,返回对应的索引值

​ ②list.insert(下标,元素值):在指定的下标,插入指定元素

​ ③list.append(元素值):将该元素值插入到尾部

​ ④list.extend(其他数据容器):将该数据容器的元素依次取出,然后挨个添加到尾部

​ ⑤del list[下标]:删除指定下标的值

​ ⑥list.pop(下标):删除指定下标的值,并返回该值

​ ⑦list.remove(元素值):删除第一个指定元素值

​ ⑧list.clear():清空列表

​ ⑨list.count(元素值):返回指定元素值出现的次数

​ ⑩len(list):返回列表的元素数量

​ 列表的遍历

​ 方式一:使用while循环,通过外部计数变量和len()方法搭配进行遍历

​ 方式二:使用for循环。如for i in list:

tuple元组

​ 概述:元组同数组一样都是可以封装多个,不同类型的元素在内,元组是一旦定义,就不能修改(如果值为其他数据容器,则可以通过修改其他数据容器来修改)。

​ 定义方式如下:

1
2
3
4
5
6
7
8
9
#定义元组字面量
(元素,元素,元素)
#定义元组变量
变量名称 = (元素,元素,元素)
#定义空元组
变量名称 = () #方式1
变量名称 = tuple() #方式2

注意定义单个元素如,t1 = ("hello",) #一定要把逗号加上

​ 元组同数组一样通过[下标]的形式进行取值,同时也可以嵌套

​ 元组的方法:

​ ①index():查找某个数据,如果数据存在返回对应的下标,否则报错

​ ②count():统计某个数据在当前元组出现的次数

​ ③len(元组):统计元组内的元素个数

str字符串

​ 概述:也是一个不可修改的容器,所以想要修改往往是创建了一个新的字符串

​ 定义如下:

1
str = "字符串"

​ 也是通过[下标]进行取单个字符。同样遍历也是同上,可以使用while和for

​ 字符串的方法

​ ①str.index(元素值):返回指定元素值的起始下标

​ ②str.replace(字符串1,字符串2):将字符串内的全部字符串1修改为字符串,并返回一个新的字符串

​ ③str.split(分隔字符串):按照指定的分隔字符串,将字符串分为多个字符串,并存入列表当中。返回一个列表对象

​ ④str.strip(字符串):去除字符串的前后的字符串中的每一个字符,默认是去除首尾空格和回车符

​ ⑤str.count(字符串):返回字符串出现的次数

​ ⑥len(str):返回字符串的长度

序列的切片

​ 序列:内容连续、有序,可使用下标索引的一类数据容器。如列表,元组,字符串都是序列。

​ 切片:从一个序列中,取出一个子序列。

​ 语法:序列[起始下标:结束下标:步长]

1
2
3
4
5
6
7
8
表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列:
起始下标表示从何处开始,可以留空,留空视作从头开始
结束下标(不含)表示何处结束,可以留空,留空视作截取到结尾
●步长表示,依次取元素的间隔
●步长1表示,一个个取元素
步长2表示,每次跳过1个元素取
步长N表示,每次跳过N-1个元素取
步长为负数表示,反向取(注意,起始下标和结束下标也要反向标记)

set集合

​ 概述:不支持重复元素的出现,并且是无序的,所以不支持索引访问。可修改

​ 定义方法如下:

1
2
3
4
5
6
#定义集合字面量
{元素,元素,元素}
#定义集合变量
变量名称 = {元素,元素,元素}
#定义空集合
变量名称 = set()

​ 集合的方法

​ ①set.add(元素值):添加元素值

​ ②set.remove(元素值):移除指定元素值

​ ③set.pop():随机取出一个元素

​ ④set.clear():清空集合

​ ⑤集合1.difference(集合2):取出集合1和集合2的差集。(集合1有而集合2没有的)

​ ⑥集合1.difference_update(集合2):对比集合1和集合2,在集合1内,删除和集合2相同的元素。

​ ⑦集合1.union(集合2):将集合1和集合2组合成新集合

​ ⑧len(集合)

​ 集合的遍历

​ 集合不支持下标索引,所以不能用while循环去遍历,但可以用for循环

dict字典

​ 概述:以键值对的形式进行存储,和集合一样同{}进行定义。字典的key不允许重复。

​ 定义:

1
2
3
4
5
6
7
8
9
#定义字典字面量
{key:value, key:value,key:value}
#定义字典变量
my_dict = {key:value, key:value,key:value}
#定义空字典
my_dict = {}
#空字典定义方式1
my_dict = dict()
#空字典定义方式2

​ 字典可以通过key值去寻找value,如dict[“key1”]返回对应的value

​ 字典的key和value可以是任意类型,但key不能是字典。可嵌套

​ 字典的方法

​ ①字典[Key]= Value:进行添加或更新字典

​ ②字典.pop(Key):删除指定key和对应的值,同时返回这个值

​ ③字典.clear():清空字典

​ ④字典.keys():获取字典中所有key,以元组的形式返回,并且元组里面只有一个包含所有key的列表

​ ⑤len(字典)

​ 字典的遍历

​ 方式一:通过keys()方法获取所有key,然后用for循环进行依次遍历

各个数据容器的对比

各个数据容器的通用操作

​ 5个数据容器都支持for循环进行遍历,只有列表,元组,字符出支持while循环遍历(因为他们支持下标索引)

​ 共有的方法,len(),max(),min()

​ 强转操作:

​ ①list(容器):字符串转列表,会将每一个字符当成一个分开,字典转列表会把value扔掉。

​ ②str(容器):列表和元组转字符串会带上他们本身的符号

​ ③tuple(容器)

​ ④set(容器)

​ sorted(容器,reverse=True):将给定容器进行排序,默认为正序,返回一个列表对象

进阶

文件操作

文件读取

​ 首先是文件的操作步骤:

​ ①打开文件

​ ②读写文件(可以没有)

​ ③关闭文件

open()函数

​ 概述:可以打开一个已经存在的文件,或者创建一一个新文件

​ 使用:open(name, mode, encoding)

1
2
3
4
5
6
7
解释:
name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。
mode:设置打开文件的模式(访问模式):只读、写入、追加等。
encoding :编码格式(推荐使用UTF-8)
实列代码:
f= open('python.txt', 'r', encoding=" UTF-8)
#其中f是文件对象,encoding的顺序不是第三位,所以不能用位置参数,用关键字参数直接指定

​ open函数的3种访问模式

read()函数

​ 使用:文件对象.read(num)

​ 解释:num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据。

​ 注意:如果在一次读取操作中多次调用read,那么下一次的read会从上一次读取结尾的地方继续读取。

readlines()函数

​ 概述:readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。

​ 注意:他会读取到换行符\n

readline()函数

​ 概述:一次读取一行的数据。通常搭配for循环进行读取

close()函数

​ 概述:释放文件的使用权

with open

1
2
3
4
5
with open("python.txt", "r") as f:
for line in f:
print(f"每一行数据是:{line}")
#通过在with open的语句块中对文件进行操作
#可以在操作完成后自动关闭close文件,避免遗忘掉close方法

文件写入

​ 与读取多了一个刷新的步骤,刷新写在写入之后。

write()函数

​ 注意:

​ ①直接调用write, 内容并未真正写入文件,而是会积攒在程序的内存中,称之为缓冲区

​ ②当调用flush的时候, 内容会真正写入文件

​ ③这样做是避免频繁的操作硬盘,导致效率下降(即攒一堆,一次性写磁盘)

异常

捕获异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
基本捕获
try:
可能发生错误的代码
except:
如果出现异常执行的代码

捕获指定异常
try:
可能发生错误的代码
except 异常名 as e:
如果出现异常执行的代码 #其中e是异常的对象

捕获多个异常
try:
可能发生错误的代码
except (异常1,异常2....) as e:
如果出现异常执行的代码

捕获全部异常
try:
可能发生错误的代码
except Exception as e:
如果出现异常执行的代码 #同基础捕获一样的都是全部
1
2
3
4
5
6
7
else:表示的是如果没有异常要执行的代码。(可省略)
try:
print(1)
except Exception as e:
print(e)
else:
print("我是else,是没有异常的时候执行的代码")
1
2
3
4
5
6
7
8
9
10
finally:表示无论如何都会执行的。(可不写)
try:
print(1)
except Exception as e:
print(e)
else:
print("我是else,是没有异常的时候执行的代码")
finlly:
print("我必须执行")
f.close()

异常的传递

​ 异常具有传递性

模块

​ python模块(model):他是一个Python文件,以.py 结尾。模块能定义函数,类和变量,模块里也能包含可执行的代码.

​ 导入方式:(from 模块名) import (模块|类|变量|函数|* ) (as 别名) #加上括号表示可选

1
2
3
4
5
6
常用组合
import 模块名
from 模块名 import 类、变量、方法等
from 模块名 import *
import 模块名 as 别名
from 模块名 import 功能名 as 别名

​ 使用:模块名.功能名()或者功能名()

​ 自定义模块注意事项:

​ ①自定义模块的模块名必须要符合标识符的命名规则

​ ②如果有多个模块相同的方法名,在只调用方法而不加模块名时,会使用后导入的模块方法

​ ③在调用其他模块的时候,会直接把被调用模块的代码执行一遍,如果不想部分语句执行,那将该部分语句放到main入口里面

1
2
if __name__ == '__main__':			#main入口
解释:这个__name__是一个内置变量,当右键运行的时候,这个变量的名称就会标记为main。也就是当运行的时候,这个if为true才会执行。

​ ④如果一个模块文件中有__ all __列表, 当使用from xxx import * 导入时,只能导入all列表中的方法名

​ 概述:从物理上看,包就是一个文件夹,在该文件夹下包含了一个__init__.py文件,这个文件表明这是一个python的包,该文件夹可用于包含多个模块文件。从逻辑上看,包的本质依然是模块。

​ 作用:帮助管理模块,它本身是一个模块

导入包

​ 方式一:

1
2
import 包名.模块名
包名.模块名.目标

​ 方式二:

1
2
3
必须在_init_.py"文件中添加'_all_ = []',控制允许导入的模块列表
注意这个all控制的是form *的方式。

高级

Json格式

​ 概述:JavaScript 对象表示法(JavaScript Object Notation)。JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去组织和封装数据

​ 本质:JSON本质上是一个带有特定格式的字符串

​ 主要功能: json就是一种在各个编程语言中流通的数据格式,负责不同编程语言中的数据传递和交互。

​ 格式:JSON数据由键值对组成,每个键值对之间用逗号分隔,整个数据以大括号 {} 包裹表示一个对象,或者以中括号 [] 包裹表示一个数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
可以是字典,也可以是列表中嵌套字典
例1:json数值
{
"key1":100,
"key2":20
}
例2:json字符串
{
"key1" : "张三",
"key2" : "大忽悠"
}
例3:json数组
people =
[
{"name": "John", "age": 30},
{"name": "Alice", "age": 25}
]

python数据和json数据的转化

1
2
3
4
5
6
7
8
#导入json模块
import json
#准备符合格式json格式要求的python数据
data = [{"name": "老王", "age": 16}, {"name": "张三", "age": 20}]
#通过json.dumps(data)方法把python数据转化为了json数据
data = json.dumps(data) #中文有乱码,可以在该方法加入参数ensure_ascii=False,即不使用ascii码进行编译直接展示。
#通过json.loads(data)方法把json数据转化为了python数据
data = json.loads(data)

面向对象

快速入门:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1.设计一个类(类比生活中:设计一张登记表)
cLass Student:
name = None #记录学生姓名
gender = None #记录学生性别
nationality = None #记录学生国籍
native_ pLace = None #记录学生籍贯
age = None #记录学生年龄
# 这个初始化可以省略
# 2.创建一个对象(类比生活中:打印一张登记表)
stu_1 = Student()

# 3.对象属性进行赋值(类比生活中:填写表单)
stu_1.name = "林军杰"
stu_1.gender = "男"
stu_1.nationality = "中国"
stu_1.native_place = "山东省"
stu_1.age = 31
# 4.获取对象中记录的信息
print(stu_1.name)

语法:

1
2
3
4
5
class  类名称:
类的属性
类的行为
其中class是关键字,用于定义类。类的属性即定义在类中的变量(成员变量)。类的行为,即定义在类中的函数(成员方法)
创建类对象的语法:对象 = 类名称()

成员方法

在类中定义成员方法和定义函数基本一致,但仍有细微区别。

1
2
3
4
5
6
7
8
9
定义格式:
def 方法名(se1f, 形参1, ....... ,形参N) :
方法体
可以看到,在方法定义的参数列表中,有一-个: self关键字
self关键字是成员方法定义的时候,必须填写的。
●它用来表示类对象自身的意思
●当我们使用类对象调用方法的是,self会 自动被python传入
●在方法内部,想要访问类的成员变量,必须使用self
self关键字,尽管在参数列表中,但是传参的时候可以忽略它。

构造方法

1
2
3
4
Python类可以使用:__init__(self)方法, 称之为构造方法。
可以实现:
●在创建类对象(构造类)的时候,会自动执行。
●在创建类对象(构造类)的时候,将传入参数自动传递给__init__方法使用。

注意:在方法内使用成员变量需要使用self。

魔术方法

​ 概述:init构造方法, 是Python类内置的方法之一。这些内置的类方法,各自有各自特殊的功能,这些形如__方法名__内置方法我们称之为魔术方法。

​ 如下图举一下常见的方法:

str方法:控制类对象被转换为字符串的输出格式
1
2
3
4
例子:
def __str__ (se1f):
return f"student类对象,name={se1f.name},age={se1f.age}"
默认输出对象,是输出对象的内存地址

​ lt方法:当直接比较两个对象的时候,是无法进行比较的,使用lt方法就可以自行定义比较模式

1
2
3
4
def __1t__(se1f,other) :
return se1f.age < other.age
传入参数:other(另一个类对象)
返回值: True或False

​ le方法:同lt方法作用一样,不过可以使用小于等于或者大于等于

​ eq方法:可以让对象进行相等的判断,判断模式自定义

封装

​ 私有的定义:

1
2
3
4
5
6
7
8
9
10
11
定义私有成员的方式只需要:
●私有成员变量:变量名以_开头(2个下划线)
●私有成员方法:方法名以_开头(2个下划线)
即可完成私有成员的设置

特点:
私有方法无法直接被类对象使用
私有变量无法赋值,也无法获取值
私有成员无法被类对象直接使用,但是可以被其它的成员使用。如通过self使用。(简单来说就是可以被类内部使用,外部就不能了)


继承

​ 概述:继承就是一个类,继承另外-一个类的成员变量和成员方法

单继承

​ 格式:

1
2
class 类名(父类类名):
类内容体

多继承

​ 格式:

1
2
3
4
class 类名(父类1,父类2,父类n):
类内容体
pass
pass的作用:当不想添加新的内容,且又为空的时候,可以使用pass表示到这里就没有了。

​ 注意:多个父类中,如果有同名的成员,那么默认以继承顺序(从左到右)为优先级。即:先继承的保留,后继承的被覆盖。

复写

​ 概述:子类继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写。即:在子类中重新定义同名的属性或方法即可。

调用父类同名成员

​ 场景:一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员,如果需要使用被复写的父类的成员,需要特殊的调用方式。

1
2
3
4
5
6
7
8
方式1:
●调用父类成员
使用成员变量:父类名.成员变量
使用成员方法:父类名.成员方法(self)
方式2:
●使用super()调用父类成员
使用成员变量: super().成员变量
使用成员方法: super().成员方法()

​ 注意:只可以在子类内部调用父类的同名成员,子类的实体类对象调用默认是调用子类复写的

类型注解

​ 概述:在代码中涉及数据交互的地方,提供数据类型的注解( 显式的说明)。

​ 作用:以方便静态类型检查工具,IDE等第三方工具。

变量的类型注解

​ 语法:变量:类型

​ 注意:

​ 元组类型设置类型详细注解,需要将每-一个元素都标记出来

​ 字典类型设置类型详细注解,需要2个类型,第一个是key第二个是value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
例子:
#基础数据类型注解
var_1: int = 10
var_2: str = "itheima"
var_3: booL = True

#类对象类型注解
cLass Student:
pass
stu: Student = Student()

#基础容器类型注解
my_list: list = [1, 2, 3]
my_tuple: tuple = (1, 2, 3)
my_dict: dict = {"itheima": 666}

#容器类型详细注解
my_list: list[int] = [1, 2, 3]
my_tuple: tuple[int, str, bool] = (1, "itheima", True)
my_dict: dict[str, int] = {"itheima": 666}

#在注释中进行类型注解
var_1 = random.randint(1, 10) # type: int
var_2 = json.loads('{"name": "zhangsan"}') # type: dict[str, str]

函数的类型注解

​ 格式:def 函数方法名(形参名:类型,形参名:类型,……) -> 返回值类型:

Union类型

​ 概述:使用要先导包typing.union。他表示这是一种联合类型。如Union[str, int]

多态

​ 概述:多态,指的是多种状态,即完成某个行为时,使用不同的对象会得到不同的状态。

1
2
3
4
5
6
7
8
9
10
11
多态常作用在继承关系上。
比如:函数(方法)形参声明接收父类对象,实际传入父类的子类对象进行工作。
即:以父类做定义声明,以子类做实际工作,用以获得同一行为,不同状态。

多态还会用在抽象类即接口上
抽象类:含有抽象方法的类称之为抽象类
抽象方法:方法体是空实现的(pass) 称之为抽象方法

这种设计的含义是:
●父类用来确定有哪些方法
●具体的方法实现,由子类自行决定

闭包

​ 场景:既想依赖全局变量,又不想全局变量被随意修改。

​ 概述:在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称为闭包。

​ 在闭包修改外部函数变量的值,需要使用nonlocal关键字修饰外部函数的变量才可在内部函数中修改它

1
2
3
4
5
6
7
8
例子:
def.outer(num1):
def inner(num2):
nonlocal num1
num1 += num2
print(num1)
return inner
这个inner就是一个闭包,且通过nonlocal进行修改num1的值

优点:

​ ①无需定义全局变量即可实现通过函数,持续的访问、修改某个值.

​ ②闭包使用的变量的所用于在函数内,难以被错误的调用修改

缺点:

​ ①由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放, 一直占用内存

装饰器

​ 概述:装饰器其实也是一种闭包,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。

​ 闭包写法:即在闭包函数内部完成功能的添加

​ 语法糖写法:使用@outer,定义在目标函数sleep之上,本质就是将该注解下的函数当作参数传入outer函数中了。所以调用直接调用被注解的函数即可。

设计模式

​ 概述:设计模式是一种编程套路,可以方便开发。

单例模式

​ 概述:单例模式(Singleton Pattern) 是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。

​ 场景:某些场景下,我们需要一个类无论获取多少次类对象,都仅仅提供一个具体的实例,用以节省创建类对象的开销和内存开销,比如某些工具类,仅需要1个实例,即可在各处使用,这就是单例模式所要实现的效果。

​ 定义:保证一个类只有一个实例,并提供一个访问它的全局访问点

​ 适用场景:当一个类只能有一个实例,而客户可以从一个众所周知的访问点访问它时。如工具类

工厂模式

​ 概述:即从原生的使用类的构造去创建对象的形式,迁移到,基于工厂提供的方法去创建对象的形式。

​ 场景:当需要大量创建一个类的实例的时候,可以使用工厂模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
例子
class Person:
pass
class Worker(Person) :
pass
class Student (Person) :
pass
cLass Teacher(Person) :
pass

class PersonFactory:
def get.person(self, p_type):
if p_type == 'w':
return Worker()
elif p_type == 's' :
return Student()
eLse:
return Teacher()

pf = PersonFactory()
worker = pf.get_person('w')
stu = pf.get_person('s')
teacher = pf.get_person('t')

优点:

​ ●大批量创建对象的时候有统一的入口,易于代码维护

​ ●当发生修改,仅修改工厂类的创建方法即可

​ ●符合现实世界的模式,即由工厂来制作产品(对象)

多线程

​ 进程:就是一个程序,运行在系统之上,那么便称之这个程序为一个运行进程,并分配进程ID方便系统管理。

​ 线程:线程是归属于进程的,一个进程可以开启多个线程,执行不同的工作,是进程的实际工作最小单位。

​ 注意:

​ ①进程之间是内存隔离的,即不同的进程拥有各自的内存空间。

​ ②线程之间是内存共享的,线程是属于进程的,一个进程内的多个线程之间是共享这个进程所拥有的内存空间的。

​ ③进程之间是并行执行,线程也可也。

​ python通过threading模块实现多线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import threading
thread_obj = threading.Thread([group [,target [, name [,args [, kwargs]]]]])
- group:暂时无用,未来功能的预留参数
- target: 执行的目标任务名
- args: 以元组的方式给执行任务传参
- kwargs: 以字典方式给执行任务传参
- name: 线程名,一般不用设置
#启动线程,让线程开始工作
thread_obj.start()

多个线程,创建多个Thread即可

需要传参的话可以通过:
●args参数通过元组(按参数顺序)的方式传参
●或使用kwargs参数用字典的形式传参

网络编程

socket

​ 概述:socket (简称套接字)是进程之间通信一个工具,好比现实生活中的插座,所有的家用电器要想工作都是基于插座进行。

​ 作用:进程之间想要进行网络通信需要socket。Socket负责进程之间的网络数据传输,好比数据的搬运工。

​ 2个进程之间通过Socket进行相互通讯,就必须有服务端和客户端

​ Socket服务端:等待其它进程的连接、可接受发来的消息、可以回复消息

​ Socket客户端:主动连接服务端、可以发送消息、可以接收回复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
1.创建socket对象
import socket
socket_server = socket.socket ()
2.绑定socket server到指定IP和地址
socket_ server.bind(host,port)
3.服务端开始监听端口
socker_server.listen(back1og)
# backlog为int整数,表示允许的连接数量,超出的会等待,可以不填,不填会自动设置一个合理值
4.接收客户端连接,获得连接对象
conn,address = socket_server.accept ()
print(f"接收到客户端连接,连接来自: {address}")
# accept方法是阻塞方法,如果没有连接,会卡再当前这一行不向下执行代码
# accept返回的是一个二元元组,可以使用上述形式,用两个变量接收二元元组的2个元素

5.客户端连接后,通过recv方法,接收客户端发送的消息
while True:
data = conn.recv(1024).decode("UTF-8")
# recv方法的返回值是字节数组(Bytes),可以通过decode使用UTF - 8解码为字符串
# recv方法的传参是buffsize,缓冲区大小,一般设置为1024即可
if data == 'exit' :
break
print ("接收到发送来的数据:”,data)
#可以通过while True无限循环来持续和客户端进行数据交互
#可以通过判定客户端发来的特殊标记,如exit,来退出无限值环
6.通过conn (客户端当次连接对象),调用send方法可以回复消息
while True:
data = conn.recv (1024) . decode("UTF-8")
if data == 'exit' :
break
print ("接收到发送来的数据: ",data)
conn.send("你好呀哈哈哈".encode("UTF-8))
7. conn (客户端当次连接对象)和socket_server对 象调用close方法,关闭连接
conn.close ( )
socket_server.close( )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
客户端编程,主要分为如下几个步骤:
1.创建socket对象
import socket
socket_client = socket. socket()
2.连接到服务端
socket_client.connect("locaLhost",8888))
3.发送消息
while True:
#可以通过无限循环来确保持续的发送消息给服务端
send_msg = input("请输入要发送的消息 ")
if send_msg = 'exit' :
#通过特殊标记来确保可以退出无限循环
break
socket_client.send(send_msg.encode("UTF-8")) #消息需要编码为字节数组 (UTF-8编码)
4.接收返回消息
while True:
send_msg = input("请输入要发送的消息") . encode("UTF-8")
socket_client.send(send_msg)
recv_data = socket_client.recv(1024) # 1024是缓冲区大小,一般1024即可
# recv方法是阻塞式的,即不接收到返回,就卡在这里等待
print("服务端回复消息为: ",recv_data.decode("UTF-8")) # 接受的消息需要通过UTF- 8解码为字符串
5.关闭链接
socket_client.close()
#最后通过close关闭链接

正则表达式

​ 概述:正则表达式,又称规则表达式( Regular Expression),是使用单个字符串来描述、匹配某个句法规则的字符串,常被用来检索、替换那些符合某个模式(规则)的文本。

​ 简单来说:正则表达式就是使用字符串定义规则,并通过规则去验证字符串是否匹配。

​ Python正则表达式,使用re模块,并基于re模块中三个基础方法来做正则匹配。

​ 分别是:match、search、findall三个基础方法

1
2
3
4
5
6
7
8
9
10
11
●re.match( 匹配规则,被匹配字符串)
从被匹配字符串开头进行匹配,匹配成功返回匹配对象(包含匹配的信息),匹配不成功返回空。
S ='python itheima python itheima python itheima '
result = re.match( 'python', s)
print(result) # <re.Match object; span=(0, 6), match=' python'>
print(result.span()) # (0, 6)
print(result.group()) # python

S = '1python itheima python itheima python itheima'
result = re.match('python', s)
print(resuLt) # None
1
2
3
4
5
6
7
8
9
10
11
12
13
●search(匹配规则, 被匹配字符 串)
搜索整个字符串,找出匹配的。从前向后,找到第一个后,就停止,不会继续向后
s = '1python666itheima666python666 '
result = re.search( 'python', s)
print (result) # <re.Match object; span=(1, 7), match='python'>
print(result. span()) # (1,7)
print(result . group()) # python

整个字符串都找不到,返回None
s = 'itheima666 '
result = re.search('python', s)
print(result)
# None
1
2
3
4
5
6
7
8
9
10
11
●findall(匹配规则,被匹配字符串)
匹配整个字符串,找出全部匹配项
s ='1python66itheima666python666’
result = re.findall('python', s)
print(result) # ['python', 'python']

找不到返回空list: []
S = '1python66itheima666python666'
result = re.findall('itcast', s)
print(result) # []

单字符匹配

数量匹配

边界和分组匹配

递归

1
2
3
4
5
6
7
8
9
1.什么是递归
在满足条件的情况下,函数自己调用自己的一种特殊编程技巧.
2.递归需要注意什么?
注意退出的条件,否则容易变成无限递归
注意返回值的传递,确保从最内层,层层传递到最外层
3. os模块的3个方法
os.listdir,列出指定目录下的内容
os.path.isdir,判断给定路径是否是文件夹,是返回True,否返回False
os.path.exists,判断给定路径是否存在,存在返回True,否则返回False