最后
Python崛起并且风靡,因为优点多、应用领域广、被大牛们认可。学习 Python 门槛很低,但它的晋级路线很多,通过它你能进入机器学习、数据挖掘、大数据,CS等更加高级的领域。Python可以做网络应用,可以做科学计算,数据分析,可以做网络爬虫,可以做机器学习、自然语言处理、可以写游戏、可以做桌面应用…Python可以做的很多,你需要学好基础,再选择明确的方向。这里给大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!
👉Python所有方向的学习路线👈
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
👉Python必备开发工具👈
工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。
👉Python全套学习视频👈
我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。
👉实战案例👈
学python就与学数学一样,是不能只看书不做题的,直接看步骤和答案会让人误以为自己全都掌握了,但是碰到生题的时候还是会一筹莫展。
因此在学习python的过程中一定要记得多动手写代码,教程只需要看一两遍即可。
👉大厂面试真题👈
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
需要这份系统化学习资料的朋友,可以戳这里获取
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
dict2 = {}
dict3 = dict()
>
> 注意:一般称冒号前面的为键(key),简称k;冒号后面的为值(value),简称v。
>
>
>
#### 字典常见操作
### 增
写法:==字典序列[key] = 值==
>
> 注意:如果key存在则修改这个key对应的值;如果key不存在则新增此键值对。
>
>
>
dict1 = {‘name’: ‘Tom’, ‘age’: 20, ‘gender’: ‘男’}
dict1[‘name’] = ‘Rose’
结果:{‘name’: ‘Rose’, ‘age’: 20, ‘gender’: ‘男’}
print(dict1)
dict1[‘id’] = 110
{‘name’: ‘Rose’, ‘age’: 20, ‘gender’: ‘男’, ‘id’: 110}
print(dict1)
>
> 注意:字典为可变类型。
>
>
>
### 删
* del() / del:删除字典或删除字典中指定键值对。
dict1 = {‘name’: ‘Tom’, ‘age’: 20, ‘gender’: ‘男’}
del dict1[‘gender’]
结果:{‘name’: ‘Tom’, ‘age’: 20}
print(dict1)
* clear():清空字典
dict1 = {‘name’: ‘Tom’, ‘age’: 20, ‘gender’: ‘男’}
dict1.clear()
print(dict1) # {}
### 改
写法:==字典序列[key] = 值==
>
> 注意:如果key存在则修改这个key对应的值 ;如果key不存在则新增此键值对。
>
>
>
### 查
#### 值查找
dict1 = {‘name’: ‘Tom’, ‘age’: 20, ‘gender’: ‘男’}
print(dict1[‘name’]) # Tom
print(dict1[‘id’]) # 报错
>
> 如果当前查找的key存在,则返回对应的值;否则则报错。
>
>
>
#### get()
* 语法
字典序列.get(key, 默认值)
>
> 注意:如果当前查找的key不存在则返回第二个参数(默认值),如果省略第二个参数,则返回None。
>
>
>
* 快速体验
dict1 = {‘name’: ‘Tom’, ‘age’: 20, ‘gender’: ‘男’}
print(dict1.get(‘name’)) # Tom
print(dict1.get(‘id’, 110)) # 110
print(dict1.get(‘id’)) # None
#### keys()
dict1 = {‘name’: ‘Tom’, ‘age’: 20, ‘gender’: ‘男’}
print(dict1.keys()) # dict_keys([‘name’, ‘age’, ‘gender’])
#### values()
dict1 = {‘name’: ‘Tom’, ‘age’: 20, ‘gender’: ‘男’}
print(dict1.values()) # dict_values([‘Tom’, 20, ‘男’])
#### items()
dict1 = {‘name’: ‘Tom’, ‘age’: 20, ‘gender’: ‘男’}
print(dict1.items()) # dict_items([(‘name’, ‘Tom’), (‘age’, 20), (‘gender’, ‘男’)])
#### 总结
* 定义字典
dict1 = {‘name’: ‘Python’, ‘age’: 30}
dict2 = {}
dict3 = dict()
* 常见操作
+ 增/改
字典序列[key] = 值
* 查找
+ 字典序列[key]
+ keys()
+ values()
+ items()
![](https://yyzqsoft.com/uploads/202407/04/5667e483e2137d9f.webp)
### 集合
#### 创建集合
创建集合使用`{}`或`set()`, 但是如果要创建空集合只能使用`set()`,因为`{}`用来创建空字典。
s1 = {10, 20, 30, 40, 50}
print(s1)
s2 = {10, 30, 20, 10, 30, 40, 30, 50}
print(s2)
s3 = set(‘abcdefg’)
print(s3)
s4 = set()
print(type(s4)) # set
s5 = {}
print(type(s5)) # dict
>
> 特点:
>
>
> 1. 集合可以去掉重复数据;
> 2. 集合数据是无序的,故不支持下标
>
>
>
#### 集合常见操作方法
### 增加数据
* add()
s1 = {10, 20}
s1.add(100)
s1.add(10)
print(s1) # {100, 10, 20}
>
> 因为集合有去重功能,所以,当向集合内追加的数据是当前集合已有数据的话,则不进行任何操作。
>
>
>
* update(), 追加的数据是序列。
s1 = {10, 20}
s1.update(100) # 报错
s1.update([100, 200])
s1.update(‘abc’)
print(s1)
### 删除数据
* remove(),删除集合中的指定数据,如果数据不存在则报错。
s1 = {10, 20}
s1.remove(10)
print(s1)
s1.remove(10) # 报错
print(s1)
* discard(),删除集合中的指定数据,如果数据不存在也不会报错。
s1 = {10, 20}
s1.discard(10)
print(s1)
s1.discard(10)
print(s1)
* pop(),随机删除集合中的某个数据,并返回这个数据。
s1 = {10, 20, 30, 40, 50}
del_num = s1.pop()
print(del_num)
print(s1)
### 查找数据
* in:判断数据在集合序列
* not in:判断数据不在集合序列
s1 = {10, 20, 30, 40, 50}
print(10 in s1)
print(10 not in s1)
#### 总结
* 创建集合
+ 有数据集合
s1 = {数据1, 数据2, …}
+ 无数据集合
s1 = set()
* 常见操作
+ 增加数据
- add()
- update()
+ 删除数据
- remove()
- discard()
![](https://yyzqsoft.com/uploads/202407/04/2c96cbc1fa577d08.webp)
### 公共操作
#### 运算符
| 运算符 | 描述 | 支持的容器类型 |
| --- | --- | --- |
| + | 合并 | 字符串、列表、元组 |
| \* | 复制 | 字符串、列表、元组 |
| in | 元素是否存在 | 字符串、列表、元组、字典 |
| not in | 元素是否不存在 | 字符串、列表、元组、字典 |
### +
1. 字符串
str1 = ‘aa’
str2 = ‘bb’
str3 = str1 + str2
print(str3) # aabb
2. 列表
list1 = [1, 2]
list2 = [10, 20]
list3 = list1 + list2
print(list3) # [1, 2, 10, 20]
3. 元组
t1 = (1, 2)
t2 = (10, 20)
t3 = t1 + t2
print(t3) # (10, 20, 100, 200)
### \*
1. 字符串
print(‘-’ * 10) # ----------
2. 列表
list1 = [‘hello’]
print(list1 * 4) # [‘hello’, ‘hello’, ‘hello’, ‘hello’]
3. 元组
t1 = (‘world’,)
print(t1 * 4) # (‘world’, ‘world’, ‘world’, ‘world’)
### in或not in
1. 字符串
print(‘a’ in ‘abcd’) # True
print(‘a’ not in ‘abcd’) # False
2. 列表
list1 = [‘a’, ‘b’, ‘c’, ‘d’]
print(‘a’ in list1) # True
print(‘a’ not in list1) # False
3. 元组
t1 = (‘a’, ‘b’, ‘c’, ‘d’)
print(‘aa’ in t1) # False
print(‘aa’ not in t1) # True
#### 公共方法
| 函数 | 描述 |
| --- | --- |
| len() | 计算容器中元素个数 |
| del 或 del() | 删除 |
| max() | 返回容器中元素最大值 |
| min() | 返回容器中元素最小值 |
| range(start, end, step) | 生成从start到end的数字,步长为 step,供for循环使用 |
| enumerate() | 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。 |
### len()
1. 字符串
str1 = ‘abcdefg’
print(len(str1)) # 7
2. 列表
list1 = [10, 20, 30, 40]
print(len(list1)) # 4
3. 元组
t1 = (10, 20, 30, 40, 50)
print(len(t1)) # 5
4. 集合
s1 = {10, 20, 30}
print(len(s1)) # 3
5. 字典
dict1 = {‘name’: ‘Rose’, ‘age’: 18}
print(len(dict1)) # 2
### del()
1. 字符串
str1 = ‘abcdefg’
del str1
print(str1)
2. 列表
list1 = [10, 20, 30, 40]
del(list1[0])
print(list1) # [20, 30, 40]
### max()
1. 字符串
str1 = ‘abcdefg’
print(max(str1)) # g
2. 列表
list1 = [10, 20, 30, 40]
print(max(list1)) # 40
### min()
1. 字符串
str1 = ‘abcdefg’
print(min(str1)) # a
2. 列表
list1 = [10, 20, 30, 40]
print(min(list1)) # 10
### range()
1 2 3 4 5 6 7 8 9
for i in range(1, 10, 1):
print(i)
1 3 5 7 9
for i in range(1, 10, 2):
print(i)
0 1 2 3 4 5 6 7 8 9
for i in range(10):
print(i)
>
> 注意:range()生成的序列不包含end数字。
>
>
>
### enumerate()
* 语法
enumerate(可遍历对象, start=0)
>
> 注意:start参数用来设置遍历数据的下标的起始值,默认为0。
>
>
>
* 快速体验
list1 = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’]
for i in enumerate(list1):
print(i)
for index, char in enumerate(list1, start=1):
print(f’下标是{index}, 对应的字符是{char}')
#### 容器类型转换
### tuple()
作用:将某个序列转换成元组
list1 = [10, 20, 30, 40, 50, 20]
s1 = {100, 200, 300, 400, 500}
print(tuple(list1))
print(tuple(s1))
### list()
作用:将某个序列转换成列表
t1 = (‘a’, ‘b’, ‘c’, ‘d’, ‘e’)
s1 = {100, 200, 300, 400, 500}
print(list(t1))
print(list(s1))
### set()
作用:将某个序列转换成集合
list1 = [10, 20, 30, 40, 50, 20]
t1 = (‘a’, ‘b’, ‘c’, ‘d’, ‘e’)
print(set(list1))
print(set(t1))
>
> 注意:
>
>
>
1. 集合可以快速完成列表去重
2. 集合不支持下标
#### 总结
* 运算符
+ +
+ in / not in
* 公共方法
+ len()
+ del()
+ range()
+ enumerate()
* 数据类型转换
+ tuple()
+ list()
+ set()
![](https://yyzqsoft.com/uploads/202407/04/0680edd27355bbbb.webp)
### 推导式
作用:用一个表达式创建一个有规律的列表或控制一个有规律列表。
列表推导式又叫列表生成式。
### 快速体验
需求:创建一个0-10的列表。
* while循环实现
1. 准备一个空列表
list1 = []
2. 书写循环,依次追加数字到空列表list1中
i = 0
while i < 10:
list1.append(i)
i += 1
print(list1)
* for循环实现
list1 = []
for i in range(10):
list1.append(i)
print(list1)
* 列表推导式实现
list1 = [i for i in range(10)]
print(list1)
#### 带if的列表推导式
需求:创建0-10的偶数列表
* 方法一:range()步长实现
list1 = [i for i in range(0, 10, 2)]
print(list1)
* 方法二:if实现
list1 = [i for i in range(10) if i % 2 == 0]
print(list1)
### 多个for循环实现列表推导式
需求:创建列表如下:
[(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
* 代码如下:
list1 = [(i, j) for i in range(1, 3) for j in range(3)]
print(list1)
#### 字典推导式
思考:如果有如下两个列表:
list1 = [‘name’, ‘age’, ‘gender’]
list2 = [‘Tom’, 20, ‘man’]
如何快速合并为一个字典?
答:字典推导式
字典推导式作用:快速合并列表为字典或提取字典中目标数据。
#### 快速体验
1. 创建一个字典:字典key是1-5数字,value是这个数字的2次方。
dict1 = {i: i**2 for i in range(1, 5)}
print(dict1) # {1: 1, 2: 4, 3: 9, 4: 16}
1. 将两个列表合并为一个字典
list1 = [‘name’, ‘age’, ‘gender’]
list2 = [‘Tom’, 20, ‘man’]
dict1 = {list1[i]: list2[i] for i in range(len(list1))}
print(dict1)
1. 提取字典中目标数据
counts = {‘MBP’: 268, ‘HP’: 125, ‘DELL’: 201, ‘Lenovo’: 199, ‘acer’: 99}
需求:提取上述电脑数量大于等于200的字典数据
count1 = {key: value for key, value in counts.items() if value >= 200}
print(count1) # {‘MBP’: 268, ‘DELL’: 201}
#### 集合推导式
需求:创建一个集合,数据为下方列表的2次方。
list1 = [1, 1, 2]
代码如下:
list1 = [1, 1, 2]
set1 = {i ** 2 for i in list1}
print(set1) # {1, 4}
>
> 注意:集合有数据去重功能。
>
>
>
####
#### 总结
* 推导式的作用:简化代码
* 推导式写法
列表推导式
[xx for xx in range()]
字典推导式
{xx1: xx2 for … in …}
集合推导式
{xx for xx in …}
![](https://yyzqsoft.com/uploads/202407/04/368ec7a2af036585.webp)
### 函数一
#### 函数的作用
需求:用户到ATM机取钱:
1. 输入密码后显示"选择功能"界面
2. 查询余额后显示"选择功能"界面
3. 取2000钱后显示"选择功能"界面
>
> 特点:显示“选择功能”界面需要重复输出给用户,怎么实现?
>
>
>
函数就是将==一段具有独立功能的代码块== 整合到一个整体并命名,在需要的位置==调用这个名称==即可完成对应的需求。
>
> 函数在开发过程中,可以更高效的实现==代码重用==。
>
>
>
#### 函数的使用步骤
### 定义函数
def 函数名(参数):
代码1
代码2
…
### 调用函数
函数名(参数)
>
> 注意:
>
>
>
1. 不同的需求,参数可有可无。
2. 在Python中,函数必须==先定义后使用==。
#### 快速体验
需求:复现ATM取钱功能。
1. 搭建整体框架(复现需求)
print(‘密码正确登录成功’)
显示"选择功能"界面
print(‘查询余额完毕’)
显示"选择功能"界面
print(‘取了2000元钱’)
显示"选择功能"界面
1. 确定“选择功能”界面内容
print(‘查询余额’)
print(‘存款’)
print(‘取款’)
1. 封装"选择功能"
>
> 注意:一定是先定义函数,后调用函数。
>
>
>
封装ATM机功能选项 – 定义函数
def select_func():
print(‘-----请选择功能-----’)
print(‘查询余额’)
print(‘存款’)
print(‘取款’)
print(‘-----请选择功能-----’)
1. 调用函数
在需要显示“选择功能”函数的位置调用函数。
print(‘密码正确登录成功’)
显示"选择功能"界面 – 调用函数
select_func()
print(‘查询余额完毕’)
显示"选择功能"界面 – 调用函数
select_func()
print(‘取了2000元钱’)
显示"选择功能"界面 – 调用函数
select_func()
####
#### 函数的参数作用
思考:完成需求如下:一个函数完成两个数1和2的加法运算,如何书写程序?
定义函数
def add_num1():
result = 1 + 2
print(result)
调用函数
add_num1()
思考:上述add\_num1函数只能完成数字1和2的加法运算,如果想要这个函数变得更灵活,可以计算任何用户指定的两个数字的和,如何书写程序?
分析:用户要在调用函数的时候指定具体数字,那么在定义函数的时候就需要接收用户指定的数字。函数调用时候指定的数字和定义函数时候接收的数字即是函数的参数。
定义函数时同时定义了接收用户数据的参数a和b,a和b是形参
def add_num2(a, b):
result = a + b
print(result)
调用函数时传入了真实的数据10 和 20,真实数据为实参
add_num2(10, 20)
#### 函数的返回值作用
例如:我们去超市购物,比如买烟,给钱之后,是不是售货员会返回给我们烟这个商品,在函数中,如果需要返回结果给用户需要使用函数返回值。
def buy():
return ‘烟’
使用变量保存函数返回值
goods = buy()
print(goods)
### 应用
需求:制作一个计算器,计算任意两数字之和,并保存结果。
def sum_num(a, b):
return a + b
用result变量保存函数返回值
result = sum_num(1, 2)
print(result)
#### 函数的说明文档
思考:定义一个函数后,程序员如何书写程序能够快速提示这个函数的作用?
答:注释
思考:如果代码多,我们是不是需要在很多代码中找到这个函数定义的位置才能看到注释?如果想更方便的查看函数的作用怎么办?
答:函数的说明文档
>
> 函数的说明文档也叫函数的文档说明。
>
>
>
#### 语法
* 定义函数的说明文档
def 函数名(参数):
“”" 说明文档的位置 “”"
代码
…
* 查看函数的说明文档
help(函数名)
#### 快速体验
def sum_num(a, b):
“”" 求和函数 “”"
return a + b
help(sum_num)
####
#### 函数嵌套调用
所谓函数嵌套调用指的是==一个函数里面又调用了另外一个函数==。
* 示例
def testB():
print(‘---- testB start----’)
print(‘这里是testB函数执行的代码…(省略)…’)
print(‘---- testB end----’)
def testA():
print(‘---- testA start----’)
testB()
print(‘---- testA end----’)
testA()
>
> * 如果函数A中,调用了另外一个函数B,那么先把函数B中的任务都执行完毕之后才会回到上次 函数A执行的位置。
>
>
>
#### 函数应用
### 函数计算
1. 求三个数之和
def sum_num(a, b, c):
return a + b + c
result = sum_num(1, 2, 3)
print(result) # 6
1. 求三个数平均值
def average_num(a, b, c):
sumResult = sum_num(a, b, c)
return sumResult / 3
result = average_num(1, 2, 3)
print(result) # 2.0
#### 总结
* 函数的作用:封装代码,高效的代码重用
* 函数使用步骤
+ 定义函数
def 函数名():
代码1
代码2
…
+ 调用函数
函数名()
* 函数的参数:函数调用的时候可以传入真实数据,增大函数的使用的灵活性
+ 形参:函数定义时书写的参数(非真实数据)
+ 实参:函数调用时书写的参数(真实数据)
* 函数的返回值
+ 作用:函数调用后,返回需要的计算结果
+ 写法
return 表达式
* 函数的说明文档
+ 作用:保存函数解释说明的信息
+ 写法
def 函数名():
“”" 函数说明文档 “”"
* 函数嵌套调用:一个函数内部嵌套调用另外一个函数
![](https://yyzqsoft.com/uploads/202407/04/9f9eb6913e71680c.webp)
### 函数二
#### 变量作用域
变量作用域指的是变量生效的范围,主要分为两类:==局部变量==和==全局变量==。
* 局部变量
所谓局部变量是定义在函数体内部的变量,即只在函数体内部生效。
def testA():
a = 100
print(a)
testA() # 100
print(a) # 报错:name ‘a’ is not defined
>
> 变量a是定义在`testA`函数内部的变量,在函数外部访问则立即报错。
>
>
>
局部变量的作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量。
* 全局变量
所谓全局变量,指的是在函数体内、外都能生效的变量。
思考:如果有一个数据,在函数A和函数B中都要使用,该怎么办?
答:将这个数据存储在一个全局变量里面。
定义全局变量a
a = 100
def testA():
print(a) # 访问全局变量a,并打印变量a存储的数据
def testB():
print(a) # 访问全局变量a,并打印变量a存储的数据
testA() # 100
testB() # 100
思考:`testB`函数需求修改变量a的值为200,如何修改程序?
a = 100
def testA():
print(a)
def testB():
a = 200
print(a)
testA() # 100
testB() # 200
print(f’全局变量a = {a}') # 全局变量a = 100
思考:在`testB`函数内部的`a = 200`中的变量a是在修改全局变量`a`吗?
答:不是。观察上述代码发现,15行得到a的数据是100,仍然是定义全局变量a时候的值,而没有返回
`testB`函数内部的200。综上:`testB`函数内部的`a = 200`是定义了一个局部变量。
思考:如何在函数体内部修改全局变量?
a = 100
def testA():
print(a)
def testB():
# global 关键字声明a是全局变量
global a
a = 200
print(a)
testA() # 100
testB() # 200
print(f’全局变量a = {a}') # 全局变量a = 200
#### 多函数程序执行流程
一般在实际开发过程中,一个程序往往由多个函数(后面知识中会讲解类)组成,并且多个函数共享某些数据,如下所示:
* 共用全局变量
1. 定义全局变量
glo_num = 0
def test1():
global glo_num
# 修改全局变量
glo_num = 100
def test2():
# 调用test1函数中修改后的全局变量
print(glo_num)
2. 调用test1函数,执行函数内部代码:声明和修改全局变量
test1()
3. 调用test2函数,执行函数内部代码:打印
test2() # 100
* 返回值作为参数传递
def test1():
return 50
def test2(num):
print(num)
1. 保存函数test1的返回值
result = test1()
2.将函数返回值所在变量作为参数传递到test2函数
test2(result) # 50
#### 函数的返回值
思考:如果一个函数如些两个return (如下所示),程序如何执行?
def return_num():
return 1
return 2
result = return_num()
print(result) # 1
答:只执行了第一个return,原因是因为return可以退出当前函数,导致return下方的代码不执行。
思考:如果一个函数要有多个返回值,该如何书写代码?
def return_num():
return 1, 2
result = return_num()
print(result) # (1, 2)
>
> 注意:
>
>
> 1. `return a, b`写法,返回多个数据的时候,默认是元组类型。
> 2. return后面可以连接列表、元组或字典,以返回多个值。
>
>
>
#### 函数的参数
### 位置参数
位置参数:调用函数时根据函数定义的参数位置来传递参数。
def user_info(name, age, gender):
print(f’您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info(‘TOM’, 20, ‘男’)
>
> 注意:传递和定义参数的顺序及个数必须一致。
>
>
>
### 关键字参数
函数调用,通过“键=值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。
def user_info(name, age, gender):
print(f’您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info(‘Rose’, age=20, gender=‘女’)
user_info(‘小明’, gender=‘男’, age=16)
注意:**函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。**
### 缺省参数
缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)。
def user_info(name, age, gender=‘男’):
print(f’您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info(‘TOM’, 20)
user_info(‘Rose’, 18, ‘女’)
>
> 注意:函数调用时,如果为缺省参数传值则修改默认参数值;否则使用这个默认值。
>
>
>
### 不定长参数
不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。
* 包裹位置传递
def user_info(*args):
print(args)
(‘TOM’,)
user_info(‘TOM’)
(‘TOM’, 18)
user_info(‘TOM’, 18)
>
> 注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。
>
>
>
* 包裹关键字传递
def user_info(**kwargs):
print(kwargs)
{‘name’: ‘TOM’, ‘age’: 18, ‘id’: 110}
user_info(name=‘TOM’, age=18, id=110)
>
> 综上:无论是包裹位置传递还是包裹关键字传递,都是一个组包的过程。
>
>
>
#### 拆包和交换变量值
### 拆包
* 拆包:元组
def return_num():
return 100, 200
num1, num2 = return_num()
print(num1) # 100
print(num2) # 200
* 拆包:字典
dict1 = {‘name’: ‘TOM’, ‘age’: 18}
a, b = dict1
对字典进行拆包,取出来的是字典的key
print(a) # name
print(b) # age
print(dict1[a]) # TOM
print(dict1[b]) # 18
### 交换变量值
需求:有变量`a = 10`和`b = 20`,交换两个变量的值。
* 方法一
借助第三变量存储数据。
1. 定义中间变量
c = 0
2. 将a的数据存储到c
c = a
3. 将b的数据20赋值到a,此时a = 20
a = b
4. 将之前c的数据10赋值到b,此时b = 10
b = c
print(a) # 20
print(b) # 10
* 方法二
a, b = 1, 2
a, b = b, a
print(a) # 2
print(b) # 1
#### 引用
### 了解引用
在python中,值是靠引用来传递来的。
**我们可以用`id()`来判断两个变量是否为同一个值的引用。** 我们可以将id值理解为那块内存的地址标识。
1. int类型
a = 1
b = a
print(b) # 1
print(id(a)) # 140708464157520
print(id(b)) # 140708464157520
a = 2
print(b) # 1,说明int类型为不可变类型
print(id(a)) # 140708464157552,此时得到是的数据2的内存地址
print(id(b)) # 140708464157520
2. 列表
aa = [10, 20]
bb = aa
print(id(aa)) # 2325297783432
print(id(bb)) # 2325297783432
aa.append(30)
print(bb) # [10, 20, 30], 列表为可变类型
print(id(aa)) # 2325297783432
print(id(bb)) # 2325297783432
### 引用当做实参
代码如下:
def test1(a):
print(a)
print(id(a))
a += a
print(a)
print(id(a))
int:计算前后id值不同
b = 100
test1(b)
列表:计算前后id值相同
c = [11, 22]
test1©
#### 可变和不可变类型
所谓可变类型与不可变类型是指:数据能够直接进行修改,如果能直接修改那么就是可变,否则是不可变.
* 可变类型
+ 列表
+ 字典
+ 集合
* 不可变类型
+ 整型
+ 浮点型
+ 字符串
+ 元组
#### 总结
* 变量作用域
+ 全局:函数体内外都能生效
+ 局部:当前函数体内部生效
* 函数多返回值写法
return 表达式1, 表达式2…
* 函数的参数
+ 位置参数
- 形参和实参的个数和书写顺序必须一致
+ 关键字参数
- 写法: `key=value`
- 特点:形参和实参的书写顺序可以不一致;关键字参数必须书写在位置参数的后面
+ 缺省参数
- 缺省参数就是默认参数
- 写法:`key=vlaue`
+ 不定长位置参数
- 收集所有位置参数,返回一个元组
+ 不定长关键字参数
- 收集所有关键字参数,返回一个字典
* 引用:Python中,数据的传递都是通过引用
![](https://yyzqsoft.com/uploads/202407/04/31118583d438b6c7.webp)
### 函数三
#### 应用:学员管理系统
### 系统简介
需求:进入系统显示系统功能界面,功能如下:
* 1、添加学员
* 2、删除学员
* 3、修改学员信息
* 4、查询学员信息
* 5、显示所有学员信息
* 6、退出系统
系统共6个功能,用户根据自己需求选取。
### 步骤分析
1. 显示功能界面
2. 用户输入功能序号
3. 根据用户输入的功能序号,执行不同的功能(函数)
3.1 定义函数
3.2 调用函数
#### 需求实现
#### 显示功能界面
定义函数`print_info`,负责显示系统功能。
def print_info():
print(‘-’ * 20)
print(‘欢迎登录学员管理系统’)
print(‘1: 添加学员’)
print(‘2: 删除学员’)
print(‘3: 修改学员信息’)
print(‘4: 查询学员信息’)
print(‘5: 显示所有学员信息’)
print(‘6: 退出系统’)
print(‘-’ * 20)
print_info()
#### 用户输入序号,选择功能
user_num = input(‘请选择您需要的功能序号:’)
#### 根据用户选择,执行不同的功能
if user_num == ‘1’:
print(‘添加学员’)
elif user_num == ‘2’:
print(‘删除学员’)
elif user_num == ‘3’:
print(‘修改学员信息’)
elif user_num == ‘4’:
print(‘查询学员信息’)
elif user_num == ‘5’:
print(‘显示所有学员信息’)
elif user_num == ‘6’:
print(‘退出系统’)
>
> 工作中,需要根据实际需求调优代码。
>
>
> 1. 用户选择系统功能的代码需要循环使用,直到用户主动退出系统。
> 2. 如果用户输入1-6以外的数字,需要提示用户。
>
>
>
while True:
# 1. 显示功能界面
print_info()
# 2. 用户选择功能
user_num = input(‘请选择您需要的功能序号:’)
# 3. 根据用户选择,执行不同的功能
if user_num == ‘1’:
print(‘添加学员’)
elif user_num == ‘2’:
print(‘删除学员’)
elif user_num == ‘3’:
print(‘修改学员信息’)
elif user_num == ‘4’:
print(‘查询学员信息’)
elif user_num == ‘5’:
print(‘显示所有学员信息’)
elif user_num == ‘6’:
print(‘退出系统’)
else:
print(‘输入错误,请重新输入!!!’)
#### 定义不同功能的函数
所有功能函数都是操作学员信息,所有存储所有学员信息应该是一个==全局变量==,数据类型为==列表==。
info = []
1.3.4.1 添加学员
* 需求分析
1. 接收用户输入学员信息,并保存
2. 判断是否添加学员信息
2.1 如果学员姓名已经存在,则报错提示
2.2 如果学员姓名不存在,则准备空字典,将用户输入的数据追加到字典,再列表追加字典数据
3. 对应的if条件成立的位置调用该函数
* 代码实现
def add_info():
“”" 添加学员 “”"
# 接收用户输入学员信息
new_id = input(‘请输入学号:’)
new_name = input(‘请输入姓名:’)
new_tel = input(‘请输入手机号:’)
# 声明info是全局变量
global info
# 检测用户输入的姓名是否存在,存在则报错提示
for i in info:
if new_name == i[‘name’]:
print(‘该用户已经存在!’)
return
# 如果用户输入的姓名不存在,则添加该学员信息
info_dict = {}
# 将用户输入的数据追加到字典
info_dict[‘id’] = new_id
info_dict[‘name’] = new_name
info_dict[‘tel’] = new_tel
# 将这个学员的字典数据追加到列表
info.append(info_dict)
print(info)
#### 删除学员
* 需求分析
按用户输入的学员姓名进行删除
1. 用户输入目标学员姓名
2. 检查这个学员是否存在
2.1 如果存在,则列表删除这个数据
2.2 如果不存在,则提示“该用户不存在”
3. 对应的if条件成立的位置调用该函数
* 代码实现
删除学员
def del_info():
“”“删除学员”“”
# 1. 用户输入要删除的学员的姓名
del_name = input(‘请输入要删除的学员的姓名:’)
global info
# 2. 判断学员是否存在:如果输入的姓名存在则删除,否则报错提示
for i in info:
if del_name == i[‘name’]:
info.remove(i)
break
else:
print(‘该学员不存在’)
print(info)
#### 修改学员信息
* 需求分析
1. 用户输入目标学员姓名
2. 检查这个学员是否存在
2.1 如果存在,则修改这位学员的信息,例如手机号
2.2 如果不存在,则报错
3. 对应的if条件成立的位置调用该函数
* 代码实现
修改函数
def modify_info():
“”“修改函数”“”
# 1. 用户输入要修改的学员的姓名
modify_name = input(‘请输入要修改的学员的姓名:’)
global info
# 2. 判断学员是否存在:如果输入的姓名存在则修改手机号,否则报错提示
for i in info:
if modify_name == i [‘name’]:
i[‘tel’] = input(‘请输入新的手机号:’)
break
else:
print(‘该学员不存在’)
print(info)
####
#### 查询学员信息
* 需求分析
1. 用户输入目标学员姓名
2. 检查学员是否存在
2.1 如果存在,则显示这个学员的信息
2.2 如果不存在,则报错提示
3. 对应的if条件成立的位置调用该函数
* 代码实现
查询学员
def search_info():
“”“查询学员”“”
# 1. 输入要查找的学员姓名:
search_name = input(‘请输入要查找的学员姓名:’)
global info
# 2. 判断学员是否存在:如果输入的姓名存在则显示这位学员信息,否则报错提示
for i in info:
if search_name == i[‘name’]:
print(‘查找到的学员信息如下:----------’)
print(f"该学员的学号是{i[‘id’]}, 姓名是{i[‘name’]}, 手机号是{i[‘tel’]}")
break
else:
print(‘该学员不存在’)
####
#### 显示所有学员信息
* 需求分析
打印所有学员信息
* 代码实现
显示所有学员信息
def print_all():
“”" 显示所有学员信息 “”"
print(‘学号\t姓名\t手机号’)
for i in info:
print(f’{i[“id”]}\t{i[“name”]}\t{i[“tel”]}')
1.3.4.6 退出系统
在用户输入功能序号`6`的时候要退出系统,代码如下:
…
elif user_num == ‘6’:
exit_flag = input(‘确定要退出吗?yes or no’)
if exit_flag == ‘yes’:
break
#### 递归
递归是一种编程思想,应用场景:
1. 在我们日常开发中,如果要遍历一个文件夹下面所有的文件,通常会使用递归来实现;
2. 在后续的算法课程中,很多算法都离不开递归,例如:快速排序。
#### 递归的特点
* 函数内部自己调用自己
* 必须有出口
### 应用:3以内数字累加和
* 代码
3 + 2 + 1
def sum_numbers(num):
# 1.如果是1,直接返回1 – 出口
if num == 1:
return 1
# 2.如果不是1,重复执行累加并返回结果
return num + sum_numbers(num-1)
sum_result = sum_numbers(3)
输出结果为6
print(sum_result)
#### lambda 表达式
如果一个函数有一个返回值,并且只有一句代码,可以使用 lambda简化。
#### lambda语法
lambda 参数列表 : 表达式
>
> 注意
>
>
>
* lambda表达式的参数可有可无,函数的参数在lambda表达式中完全适用。
* lambda表达式能接收任何数量的参数但只能返回一个表达式的值。
#### 快速入门
函数
def fn1():
return 200
print(fn1)
print(fn1())
lambda表达式
fn2 = lambda: 100
print(fn2)
print(fn2())
>
> 注意:直接打印lambda表达式,输出的是此lambda的内存地址
>
>
>
### 示例:计算a + b
#### 函数实现
def add(a, b):
return a + b
result = add(1, 2)
print(result)
>
> 思考:需求简单,是否代码多?
>
>
>
#### lambda实现
fn1 = lambda a, b: a + b
print(fn1(1, 2))
### lambda的参数形式
#### 无参数
fn1 = lambda: 100
print(fn1())
#### 一个参数
fn1 = lambda a: a
print(fn1(‘hello world’))
#### 默认参数
fn1 = lambda a, b, c=100: a + b + c
print(fn1(10, 20))
#### 可变参数:\*args
fn1 = lambda *args: args
print(fn1(10, 20, 30))
>
> 注意:这里的可变参数传入到lambda之后,返回值为元组。
>
>
>
#### 可变参数:\*\*kwargs
fn1 = lambda **kwargs: kwargs
print(fn1(name=‘python’, age=20))
### lambda的应用
#### 带判断的lambda
fn1 = lambda a, b: a if a > b else b
print(fn1(1000, 500))
#### 列表数据按字典key的值排序
students = [
{‘name’: ‘TOM’, ‘age’: 20},
{‘name’: ‘ROSE’, ‘age’: 19},
{‘name’: ‘Jack’, ‘age’: 22}
]
按name值升序排列
students.sort(key=lambda x: x[‘name’])
print(students)
按name值降序排列
students.sort(key=lambda x: x[‘name’], reverse=True)
print(students)
按age值升序排列
students.sort(key=lambda x: x[‘age’])
print(students)
#### 高阶函数
==把函数作为参数传入==,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式。
### 体验高阶函数
在Python中,`abs()`函数可以完成对数字求绝对值计算。
abs(-10) # 10
`round()`函数可以完成对数字的四舍五入计算。
round(1.2) # 1
round(1.9) # 2
需求:任意两个数字,按照指定要求整理数字后再进行求和计算。
* 方法1
def add_num(a, b):
return abs(a) + abs(b)
result = add_num(-1, 2)
print(result) # 3
* 方法2
def sum_num(a, b, f):
return f(a) + f(b)
result = sum_num(-1, 2, abs)
print(result) # 3
>
> 注意:两种方法对比之后,发现,方法2的代码会更加简洁,函数灵活性更高。
>
>
>
函数式编程大量使用函数,减少了代码的重复,因此程序比较短,开发速度较快。
### 内置高阶函数
### map()
map(func, lst),将传入的函数变量func作用到lst变量的每个元素中,并将结果组成新的列表(Python2)/迭代器(Python3)返回。
需求:计算`list1`序列中各个数字的2次方。
list1 = [1, 2, 3, 4, 5]
def func(x):
return x ** 2
result = map(func, list1)
print(result) # <map object at 0x0000013769653198>
print(list(result)) # [1, 4, 9, 16, 25]
#### reduce()
reduce(func,lst),其中func必须有两个参数。每次func计算的结果继续和序列的下一个元素做累积计算。
>
> 注意:reduce()传入的参数func必须接收2个参数。
>
>
>
需求:计算`list1`序列中各个数字的累加和。
import functools
list1 = [1, 2, 3, 4, 5]
def func(a, b):
return a + b
result = functools.reduce(func, list1)
print(result) # 15
#### filter()
filter(func, lst)函数用于过滤序列, 过滤掉不符合条件的元素, 返回一个 filter 对象。如果要转换为列表, 可以使用 list() 来转换。
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def func(x):
return x % 2 == 0
result = filter(func, list1)
print(result) # <filter object at 0x0000017AF9DC3198>
print(list(result)) # [2, 4, 6, 8, 10]
#### 总结
* 递归
+ 函数内部自己调用自己
+ 必须有出口
* lambda
+ 语法
lambda 参数列表: 表达式
+ lambda的参数形式
- 无参数
```
lambda: 表达式
```
- 一个参数
```
lambda 参数: 表达式
```
- 默认参数
```
lambda key=value: 表达式
```
- 不定长位置参数
```
lambda *args: 表达式
```
- 不定长关键字参数
```
lambda **kwargs: 表达式
```
* 高阶函数
+ 作用:把函数作为参数传入,化简代码
+ 内置高阶函数
- map()
- reduce()
- filter()
![](https://yyzqsoft.com/uploads/202407/04/ee6cf69020583c5a.webp)
### 文件操作
#### 文件操作的作用
思考:什么是文件?
思考:文件操作包含什么?
答:打开、关闭、读、写、复制....
思考:文件操作的的作用是什么?
答:读取内容、写入内容、备份内容......
>
> 总结:文件操作的作用就是==把一些内容(数据)存储存放起来,可以让程序下一次执行的时候直接使用,而不必重新制作一份,省时省力==。
>
>
>
#### 文件的基本操作
### 文件操作步骤
1. 打开文件
2. 读写等操作
3. 关闭文件
>
> 注意:可以只打开和关闭文件,不进行任何读写操作。
>
>
>
#### 打开
在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件,语法如下:
open(name, mode)
name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。
mode:设置打开文件的模式(访问模式):只读、写入、追加等。
#### 打开文件模式
| 模式 | 描述 |
| --- | --- |
| r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
| rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 |
| r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
| rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 |
| w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
| a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
| ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
| a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
| ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
#### 快速体验
f = open(‘test.txt’, ‘w’)
>
> 注意:此时的`f`是`open`函数的文件对象。
>
>
>
#### 文件对象方法
写
* 语法
对象对象.write(‘内容’)
* 体验
1. 打开文件
f = open(‘test.txt’, ‘w’)
2.文件写入
f.write(‘hello world’)
3. 关闭文件
f.close()
>
> 注意:
>
>
> 1. `w`和`a`模式:如果文件不存在则创建该文件;如果文件存在,`w`模式先清空再写入,`a`模式直接末尾追加。
> 2. `r`模式:如果文件不存在则报错。
>
>
>
读
* read()
文件对象.read(num)
>
> num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据。
>
>
>
* readlines()
readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素。
f = open(‘test.txt’)
content = f.readlines()
[‘hello world\n’, ‘abcdefg\n’, ‘aaa\n’, ‘bbb\n’, ‘ccc’]
print(content)
关闭文件
f.close()
* readline()
readline()一次读取一行内容。
f = open(‘test.txt’)
content = f.readline()
print(f’第一行:{content}‘)
content = f.readline()
print(f’第二行:{content}’)
关闭文件
f.close()
#### seek()
作用:用来移动文件指针。
语法如下:
文件对象.seek(偏移量, 起始位置)
>
> 起始位置:
>
>
> * 0:文件开头
> * 1:当前位置
> * 2:文件结尾
>
>
>
#### 关闭
文件对象.close()
####
#### 文件备份
需求:用户输入当前目录下任意文件名,程序完成对该文件的备份功能(备份文件名为xx[备份]后缀,例如:test[备份].txt)。
### 步骤
1. 接收用户输入的文件名
2. 规划备份文件名
3. 备份文件写入数据
### 代码实现
1. 接收用户输入目标文件名
old_name = input(‘请输入您要备份的文件名:’)
1. 规划备份文件名
2.1 提取目标文件后缀
2.2 组织备份的文件名,xx[备份]后缀
2.1 提取文件后缀点的下标
index = old_name.rfind(‘.’)
print(index) # 后缀中.的下标
print(old_name[:index]) # 源文件名(无后缀)
2.2 组织新文件名 旧文件名 + [备份] + 后缀
new_name = old_name[:index] + ‘[备份]’ + old_name[index:]
打印新文件名(带后缀)
print(new_name)
1. 备份文件写入数据
3.1 打开源文件 和 备份文件
3.2 将源文件数据写入备份文件
3.3 关闭文件
3.1 打开文件
old_f = open(old_name, ‘rb’)
new_f = open(new_name, ‘wb’)
3.2 将源文件数据写入备份文件
while True:
con = old_f.read(1024)
if len(con) == 0:
break
new_f.write(con)
3.3 关闭文件
old_f.close()
new_f.close()
### 思考
如果用户输入`.txt`,这是一个无效文件,程序如何更改才能限制只有有效的文件名才能备份?
答:添加条件判断即可。
old_name = input(‘请输入您要备份的文件名:’)
index = old_name.rfind(‘.’)
if index > 0:
postfix = old_name[index:]
new_name = old_name[:index] + ‘[备份]’ + postfix
old_f = open(old_name, ‘rb’)
new_f = open(new_name, ‘wb’)
while True:
con = old_f.read(1024)
if len(con) == 0:
break
new_f.write(con)
old_f.close()
new_f.close()
#### 文件和文件夹的操作
在Python中文件和文件夹的操作要借助os模块里面的相关功能,具体步骤如下:
1. 导入os模块
import os
1. 使用`os`模块相关功能
os.函数名()
### 文件重命名
os.rename(目标文件名, 新文件名)
### 删除文件
os.remove(目标文件名)
### 创建文件夹
os.mkdir(文件夹名字)
### 删除文件夹
os.rmdir(文件夹名字)
### 获取当前目录
os.getcwd()
### 改变默认目录
os.chdir(目录)
### 获取目录列表
os.listdir(目录)
#### 应用案例
需求:批量修改文件名,既可添加指定字符串,又能删除指定字符串。
* 步骤
1. 设置添加删除字符串的的标识
2. 获取指定目录的所有文件
3. 将原有文件名添加/删除指定字符串,构造新名字
4. os.rename()重命名
* 代码
import os
设置重命名标识:如果为1则添加指定字符,flag取值为2则删除指定字符
flag = 1
获取指定目录
dir_name = ‘./’
获取指定目录的文件列表
file_list = os.listdir(dir_name)
print(file_list)
遍历文件列表内的文件
for name in file_list:
# 添加指定字符
if flag == 1:
new_name = ‘Python-’ + name
# 删除指定字符
elif flag == 2:
num = len(‘Python-’)
new_name = name[num:]
# 打印新文件名,测试程序正确性
print(new_name)
# 重命名
os.rename(dir_name+name, dir_name+new_name)
#### 总结
* 文件操作步骤
+ 打开
文件对象 = open(目标文件, 访问模式)
+ 操作
- 读
```
文件对象.read()
文件对象.readlines()
文件对象.readline()
```
- 写
```
文件对象.write()
```
- seek()
+ 关闭
文件对象.close()
* 主访问模式
+ w:写,文件不存在则新建该文件
+ r:读,文件不存在则报错
+ a:追加
* 文件和文件夹操作
+ 重命名:os.rename()
+ 获取当前目录:os.getcwd()
+ 获取目录列表:os.listdir()
![](https://yyzqsoft.com/uploads/202407/04/3225ff6fde523bd9.webp)
### 面向对象基础
####
#### 理解面向对象
面向对象是一种抽象化的编程思想,很多编程语言中都有的一种思想。
>
> 总结:==面向对象就是将编程当成是一个事物,对外界来说,事物是直接使用的,不用去管他内部的情况。而编程就是设置事物能够做什么事。==
>
>
>
#### 类和对象
在面向对象编程过程中,有两个重要组成部分:类 和 对象
类和对象的关系:用类去创建一个对象。
### 理解类和对象
#### 类
类是对一系列具有相同==特征==和==行为==的事物的统称,是一个==抽象的概念==,不是真实存在的事物。
* 特征即是属性
* 行为即是方法
#### 对象
对象是类创建出来的真实存在的事物
>
> 注意:开发中,先有类,再有对象。
>
>
>
### 面向对象实现方法
#### 定义类
Python2中类分为:经典类 和 新式类
* 语法
class 类名():
代码
…
>
> 注意:类名要满足标识符命名规则,同时遵循==大驼峰命名习惯==。
>
>
>
* 体验
class Washer():
def wash(self):
print(‘我会洗衣服’)
* 拓展:经典类
不由任意内置类型派生出的类,称之为经典类
class 类名:
代码
…
#### 创建对象
对象又名实例。
* 语法
对象名 = 类名()
* 体验
创建对象
haier1 = Washer()
<main.Washer object at 0x0000018B7B224240>
print(haier1)
haier对象调用实例方法
haier1.wash()
>
> 注意:创建对象的过程也叫实例化对象。
>
>
>
#### self
self指的是调用该函数的对象。
1. 定义类
class Washer():
def wash(self):
print(‘我会洗衣服’)
# <main.Washer object at 0x0000024BA2B34240>
print(self)
2. 创建对象
haier1 = Washer()
<main.Washer object at 0x0000018B7B224240>
print(haier1)
haier1对象调用实例方法
haier1.wash()
haier2 = Washer()
<main.Washer object at 0x0000022005857EF0>
print(haier2)
>
> 注意:打印对象和self得到的结果是一致的,都是当前对象的内存中存储地址。
>
>
>
#### 添加和获取对象属性
对象属性既可以在类外面添加和获取,也能在类里面添加和获取。
#### 类外面添加对象属性语法
*
对象名.属性名 = 值
* 体验
haier1.width = 500
haier1.height = 800
#### 类外面获取对象属性
* 语法
对象名.属性名
* 体验
print(f’haier1洗衣机的宽度是{haier1.width}‘)
print(f’haier1洗衣机的高度是{haier1.height}’)
### 类里面获取对象属性
* 语法
self.属性名
* 体验
定义类
class Washer():
def print_info(self):
# 类里面获取实例属性
print(f’haier1洗衣机的宽度是{self.width}‘)
print(f’haier1洗衣机的高度是{self.height}’)
创建对象
haier1 = Washer()
添加实例属性
haier1.width = 500
haier1.height = 800
haier1.print_info()
#### 魔法方法
在Python中,`__xx__()`的函数叫做魔法方法,指的是具有特殊功能的函数。
### `__init__()`
#### 体验`__init__()`
==`__init__()`方法的作用:初始化对象。==
class Washer():
# 定义初始化功能的函数
def init(self):
# 添加实例属性
self.width = 500
self.height = 800
def print_info(self):
# 类里面调用实例属性
print(f’洗衣机的宽度是{self.width}, 高度是{self.height}')
haier1 = Washer()
haier1.print_info()
>
> 注意:
>
>
> * `__init__()`方法,在创建一个对象时默认被调用,不需要手动调用
> * `__init__(self)`中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去。
>
>
>
#### 带参数的`__init__()`
思考:一个类可以创建多个对象,如何对不同的对象设置不同的初始化属性呢?
答:传参数。
class Washer():
def init(self, width, height):
self.width = width
self.height = height
def print_info(self):
print(f’洗衣机的宽度是{self.width}‘)
print(f’洗衣机的高度是{self.height}’)
haier1 = Washer(10, 20)
haier1.print_info()
haier2 = Washer(30, 40)
haier2.print_info()
### `__str__()`
当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了`__str__`方法,那么就会打印从在这个方法中 return 的数据。
class Washer():
def init(self, width, height):
self.width = width
self.height = height
def str(self):
return ‘这是海尔洗衣机的说明书’
haier1 = Washer(10, 20)
这是海尔洗衣机的说明书
print(haier1)
### `__del__()`
当删除对象时,python解释器也会默认调用`__del__()`方法。
class Washer():
def init(self, width, height):
self.width = width
self.height = height
def del(self):
print(f’{self}对象已经被删除’)
haier1 = Washer(10, 20)
<main.Washer object at 0x0000026118223278>对象已经被删除
del haier1
#### 综合应用
### 烤地瓜
#### 需求
需求主线:
1. 被烤的时间和对应的地瓜状态:
0-3分钟:生的
3-5分钟:半生不熟
5-8分钟:熟的
超过8分钟:烤糊了
2. 添加的调料:
用户可以按自己的意愿添加调料
#### 步骤分析
需求涉及一个事物: 地瓜,故案例涉及一个类:地瓜类。
5.1.2.1 定义类
* 地瓜的属性
+ 被烤的时间
+ 地瓜的状态
+ 添加的调料
* 地瓜的方法
+ 被烤
- 用户根据意愿设定每次烤地瓜的时间
- 判断地瓜被烤的总时间是在哪个区间,修改地瓜状态
+ 添加调料
- 用户根据意愿设定添加的调料
- 将用户添加的调料存储
* 显示对象信息
5.1.2.2 创建对象,调用相关实例方法
#### 代码实现
5.1.3.1 定义类
* 地瓜属性
+ 定义地瓜初始化属性,后期根据程序推进更新实例属性
class SweetPotato():
def init(self):
# 被烤的时间
self.cook_time = 0
# 地瓜的状态
self.cook_static = ‘生的’
# 调料列表
self.condiments = []
5.1.3.2 定义烤地瓜方法
class SweetPotato():
…
def cook(self, time):
“”“烤地瓜的方法”“”
self.cook_time += time
if 0 <= self.cook_time < 3:
self.cook_static = ‘生的’
elif 3 <= self.cook_time < 5:
self.cook_static = ‘半生不熟’
elif 5 <= self.cook_time < 8:
self.cook_static = ‘熟了’
elif self.cook_time >= 8:
self.cook_static = ‘烤糊了’
5.1.3.3 书写str魔法方法,用于输出对象状态
class SweetPotato():
…
def str(self):
return f’这个地瓜烤了{self.cook_time}分钟, 状态是{self.cook_static}’
5.1.3.4 创建对象,测试实例属性和实例方法
digua1 = SweetPotato()
print(digua1)
digua1.cook(2)
print(digua1)
5.1.3.5 定义添加调料方法,并调用该实例方法
class SweetPotato():
…
def add_condiments(self, condiment):
“”“添加调料”“”
self.condiments.append(condiment)
def str(self):
return f’这个地瓜烤了{self.cook_time}分钟, 状态是{self.cook_static}, 添加的调料有{self.condiments}’
digua1 = SweetPotato()
print(digua1)
digua1.cook(2)
digua1.add_condiments(‘酱油’)
print(digua1)
digua1.cook(2)
digua1.add_condiments(‘辣椒面儿’)
print(digua1)
digua1.cook(2)
print(digua1)
digua1.cook(2)
print(digua1)
#### 代码总览
定义类
class SweetPotato():
def init(self):
# 被烤的时间
self.cook_time = 0
# 地瓜的状态
self.cook_static = ‘生的’
# 调料列表
self.condiments = []
def cook(self, time):
“”“烤地瓜的方法”“”
self.cook_time += time
if 0 <= self.cook_time < 3:
self.cook_static = ‘生的’
elif 3 <= self.cook_time < 5:
self.cook_static = ‘半生不熟’
elif 5 <= self.cook_time < 8:
self.cook_static = ‘熟了’
elif self.cook_time >= 8:
self.cook_static = ‘烤糊了’
def add_condiments(self, condiment):
“”“添加调料”“”
self.condiments.append(condiment)
def str(self):
return f’这个地瓜烤了{self.cook_time}分钟, 状态是{self.cook_static}, 添加的调料有{self.condiments}’
digua1 = SweetPotato()
print(digua1)
digua1.cook(2)
digua1.add_condiments(‘酱油’)
print(digua1)
digua1.cook(2)
digua1.add_condiments(‘辣椒面儿’)
print(digua1)
digua1.cook(2)
print(digua1)
digua1.cook(2)
print(digua1)
### 搬家具
#### 需求
将小于房子剩余面积的家具摆放到房子中
#### 步骤分析
需求涉及两个事物:房子 和 家具,故被案例涉及两个类:房子类 和 家具类。
5.2.2.1 定义类
* 房子类
+ 实例属性
- 房子地理位置
- 房子占地面积
- 房子剩余面积
- 房子内家具列表
+ 实例方法
- 容纳家具
+ 显示房屋信息
* 家具类
+ 家具名称
+ 家具占地面积
5.2.2.2 创建对象并调用相关方法
#### 代码实现
5.2.3.1 定义类
* 家具类
class Furniture():
def init(self, name, area):
# 家具名字
self.name = name
# 家具占地面积
self.area = area
* 房子类
class Home():
def init(self, address, area):
# 地理位置
self.address = address
# 房屋面积
self.area = area
# 剩余面积
self.free_area = area
# 家具列表
self.furniture = []
def str(self):
return f’房子坐落于{self.address}, 占地面积{self.area}, 剩余面积{self.free_area}, 家具有{self.furniture}’
def add_furniture(self, item):
“”“容纳家具”“”
if self.free_area >= item.area:
self.furniture.append(item.name)
# 家具搬入后,房屋剩余面积 = 之前剩余面积 - 该家具面积
self.free_area -= item.area
else:
print(‘家具太大,剩余面积不足,无法容纳’)
创建对象并调用实例属性和方法
bed = Furniture(‘双人床’, 6)
jia1 = Home(‘北京’, 1200)
print(jia1)
jia1.add_furniture(bed)
print(jia1)
sofa = Furniture(‘沙发’, 10)
jia1.add_furniture(sofa)
print(jia1)
ball = Furniture(‘篮球场’, 1500)
jia1.add_furniture(ball)
print(jia1)
#### 总结
* 面向对象重要组成部分
+ 类
- 创建类
class 类名():
代码
+ 对象
对象名 = 类名()
* 添加对象属性
+ 类外面
对象名.属性名 = 值
+ 类里面
self.属性名 = 值
* 获取对象属性
+ 类外面
对象名.属性名
+ 类里面
self.属性名
* 魔法方法
+ `__init__()`: 初始化
+ `__str__()`:输出对象信息
+ `__del__()`:删除对象时调用
![](https://yyzqsoft.com/uploads/202407/04/a1f3f61d5316eb97.webp)
### 面向对象-继承
#### 继承的概念
生活中的继承,一般指的是子女继承父辈的财产。
* 拓展1:经典类或旧式类
不由任意内置类型派生出的类,称之为经典类。
class 类名:
代码
…
* 拓展2:新式类
class 类名(object):
代码
Python面向对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法,具体如下:
父类A
class A(object):
def init(self):
self.num = 1
def info_print(self):
print(self.num)
子类B
class B(A):
pass
result = B()
result.info_print() # 1
>
> 在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。
>
>
>
#### 单继承
>
> 故事主线:一个煎饼果子老师傅,在煎饼果子界摸爬滚打多年,研发了一套精湛的摊煎饼果子的技术。师父要把这套技术传授给他的唯一的最得意的徒弟。
>
>
>
分析:徒弟是不是要继承师父的所有技术?
1. 师父类
class Master(object):
def init(self):
self.kongfu = ‘[古法煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
2. 徒弟类
class Prentice(Master):
pass
3. 创建对象daqiu
daqiu = Prentice()
4. 对象访问实例属性
print(daqiu.kongfu)
5. 对象调用实例方法
daqiu.make_cake()
#### 多继承
>
> 故事推进:小明是个爱学习的好孩子,想学习更多的煎饼果子技术,于是,在百度搜索学习
>
>
>
所谓多继承意思就是一个类同时继承了多个父类。
class Master(object):
def init(self):
self.kongfu = ‘[古法煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
创建学校类
class School(object):
def init(self):
self.kongfu = ‘[煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
class Prentice(School, Master):
pass
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()
>
> 注意:当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法。
>
>
>
####
#### 子类重写父类同名方法和属性
>
> 故事:小明掌握了师父和培训的技术后,自己潜心钻研出自己的独门配方的一套全新的煎饼果子技术。
>
>
>
class Master(object):
def init(self):
self.kongfu = ‘[古法煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
class School(object):
def init(self):
self.kongfu = ‘[煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
独创配方
class Prentice(School, Master):
def init(self):
self.kongfu = ‘[独创煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()
print(Prentice.mro)
>
> 子类和父类具有同名属性和方法,默认使用子类的同名属性和方法。
>
>
>
#### 子类调用父类的同名方法和属性
>
> 故事:很多顾客都希望也能吃到古法和黑马的技术的煎饼果子。
>
>
>
class Master(object):
def init(self):
self.kongfu = ‘[古法煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
class School(object):
def init(self):
self.kongfu = ‘[黑马煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
class Prentice(School, Master):
def init(self):
self.kongfu = ‘[独创煎饼果子配方]’
def make_cake(self):
# 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
self.init()
print(f’运用{self.kongfu}制作煎饼果子’)
# 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
def make_master_cake(self):
Master.init(self)
Master.make_cake(self)
def make_school_cake(self):
School.init(self)
School.make_cake(self)
daqiu = Prentice()
daqiu.make_cake()
daqiu.make_master_cake()
daqiu.make_school_cake()
daqiu.make_cake()
#### 多层继承
>
> 故事:N年后,小明老了,想要把所有技术传承给自己的徒弟。
>
>
>
class Master(object):
def init(self):
self.kongfu = ‘[古法煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
class School(object):
def init(self):
self.kongfu = ‘[煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
class Prentice(School, Master):
def init(self):
self.kongfu = ‘[独创煎饼果子配方]’
def make_cake(self):
self.init()
print(f’运用{self.kongfu}制作煎饼果子’)
def make_master_cake(self):
Master.init(self)
Master.make_cake(self)
def make_school_cake(self):
School.init(self)
School.make_cake(self)
徒孙类
class Tusun(Prentice):
pass
xiaoqiu = Tusun()
xiaoqiu.make_cake()
xiaoqiu.make_school_cake()
xiaoqiu.make_master_cake()
#### super()调用父类方法
class Master(object):
def init(self):
self.kongfu = ‘[古法煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
class School(Master):
def init(self):
self.kongfu = ‘[煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
# 方法2.1
# super(School, self).init()
# super(School, self).make_cake()
# 方法2.2
super().init()
super().make_cake()
class Prentice(School):
def init(self):
self.kongfu = ‘[独创煎饼果子技术]’
def make_cake(self):
self.init()
print(f’运用{self.kongfu}制作煎饼果子’)
# 子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
def make_master_cake(self):
Master.init(self)
Master.make_cake(self)
def make_school_cake(self):
School.init(self)
School.make_cake(self)
# 一次性调用父类的同名属性和方法
def make_old_cake(self):
# 方法一:代码冗余;父类类名如果变化,这里代码需要频繁修改
# Master.init(self)
# Master.make_cake(self)
# School.init(self)
# School.make_cake(self)
# 方法二: super()
# 方法2.1 super(当前类名, self).函数()
# super(Prentice, self).init()
# super(Prentice, self).make_cake()
# 方法2.2 super().函数()
super().init()
super().make_cake()
daqiu = Prentice()
daqiu.make_old_cake()
>
> 注意:使用super() 可以自动查找父类。调用顺序遵循 `__mro__` 类属性的顺序。比较适合单继承使用。
>
>
>
#### 私有权限
#### 定义私有属性和方法
在Python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类。
>
> 故事:小明把技术传承给徒弟的同时,不想把自己的钱(2000000个亿)继承给徒弟,这个时候就要为`钱`这个实例属性设置私有权限。
>
>
>
设置私有权限的方法:在属性名和方法名 前面 加上两个下划线 \_\_。
class Master(object):
def init(self):
self.kongfu = ‘[古法煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
class School(object):
def init(self):
self.kongfu = ‘[煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
class Prentice(School, Master):
def init(self):
self.kongfu = ‘[独创煎饼果子配方]’
# 定义私有属性
self.__money = 2000000
# 定义私有方法
def __info_print(self):
print(self.kongfu)
print(self.__money)
def make_cake(self):
self.init()
print(f’运用{self.kongfu}制作煎饼果子’)
def make_master_cake(self):
Master.init(self)
Master.make_cake(self)
def make_school_cake(self):
School.init(self)
School.make_cake(self)
徒孙类
class Tusun(Prentice):
pass
daqiu = Prentice()
对象不能访问私有属性和私有方法
print(daqiu.__money)
daqiu.__info_print()
xiaoqiu = Tusun()
子类无法继承父类的私有属性和私有方法
print(xiaoqiu.__money) # 无法访问实例属性__money
xiaoqiu.__info_print()
>
> 注意:私有属性和私有方法只能在类里面访问和修改。
>
>
>
### 获取和修改私有属性值
在Python中,一般定义函数名`get_xx`用来获取私有属性,定义`set_xx`用来修改私有属性值。
class Master(object):
def init(self):
self.kongfu = ‘[古法煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
class School(object):
def init(self):
self.kongfu = ‘[煎饼果子配方]’
def make_cake(self):
print(f’运用{self.kongfu}制作煎饼果子’)
class Prentice(School, Master):
def init(self):
self.kongfu = ‘[独创煎饼果子配方]’
self.__money = 2000000
# 获取私有属性
def get_money(self):
return self.__money
# 修改私有属性
def set_money(self):
self.__money = 500
def __info_print(self):
print(self.kongfu)
print(self.__money)
def make_cake(self):
self.init()
print(f’运用{self.kongfu}制作煎饼果子’)
def make_master_cake(self):
Master.init(self)
Master.make_cake(self)
def make_school_cake(self):
School.init(self)
School.make_cake(self)
徒孙类
class Tusun(Prentice):
pass
daqiu = Prentice()
xiaoqiu = Tusun()
调用get_money函数获取私有属性money的值
print(xiaoqiu.get_money())
调用set_money函数修改私有属性money的值
xiaoqiu.set_money()
print(xiaoqiu.get_money())
#### 总结
* 继承的特点
+ 子类默认拥有父类的所有属性和方法
+ 子类重写父类同名方法和属性
+ 子类调用父类同名方法和属性
* super()方法快速调用父类方法
* 私有权限
+ 不能继承给子类的属性和方法需要添加私有权限
+ 语法
class 类名():
# 私有属性
__属性名 = 值
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化学习资料的朋友,可以戳这里获取
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!