📚 Python入门到高级(知识点四)
💡 关键知识点
一、函数
1. 函数的定义和调用
函数:提前组织好的,可以重复使用的,具有特定功能的代码段。
使用函数的好处:
- ✅ 提高代码复用性:避免重复编写相同的代码
- ✅ 提高代码可读性:将复杂功能封装成函数,主逻辑更清晰
- ✅ 便于维护:修改功能只需改函数内部,不影响调用处
# 需求:定义一个函数用于计算任意两个数的和
def get_sum(a, b):
sum = a + b
return sum
# 调用函数
print(get_sum(1, 2)) # 3
print(get_sum(2, 3)) # 5
print(get_sum(3, 4)) # 7
2. 全局变量与局部变量
| 变量类型 | 定义位置 | 作用范围 | 说明 |
|---|---|---|---|
| 全局变量 | 函数外部定义 | 函数内外都能访问 | 在整个文件中都可以使用 |
| 局部变量 | 函数内部定义 | 只能在所属函数内访问 | 函数执行完毕后被销毁 |
# 定义函数
def show():
# 局部变量:只能在所属函数内访问
b = 100
# 如果全局变量和局部变量同名,默认访问的是局部变量
print(a) # 10(访问全局变量)
print(b) # 100(访问局部变量)
# main:程序的入口
if __name__ == '__main__':
# 全局变量:函数内外都能访问
a = 10
# 调用 show 函数
show()
# 打印全局变量
print(a) # 10
# print(b) # ❌ 报错!局部变量 b 只能在函数内访问
3.有 global 和没有 global 的区别
| 场景 | 代码 | 结果 | 说明 |
|---|---|---|---|
| 没有 global | a = 10(全局) def test(): a = 100(局部) | 全局 a 仍为 10 | 函数内创建了新的局部变量,不影响全局变量 |
| 有 global | a = 10(全局) def test(): global a a = 100 | 全局 a 变为 100 ✅ | 函数内修改的是全局变量 |
# 先定义函数
def show():
# TODO 函数内如何修改全局变量?
# global关键字声明要求修改的是全局变量
global a
a = 100
print(a) # 100
# 再调用函数
# main:默认是程序的入口
if __name__ == '__main__':
# 全局变量: 函数内外都能访问
a = 10
# 调研show函数
show()
# 打印全局变量
print(a) # 100
注意事项
💡 开发建议:
- 全局变量和局部变量同名时,函数内默认访问局部变量(就近原则)
- 在函数内修改全局变量时,必须用
global关键字声明- 如果不使用
global,Python 会把函数内的赋值当作创建新的局部变量- 尽量少用全局变量,过多使用会导致代码难以维护和理解
4. 函数的参数传递
| 参数类型 | 说明 | 特点 |
|---|---|---|
| 位置传参 | 实参和形参按位置一一对应 | 顺序和个数必须一致 |
| 关键字传参 | 通过形参名指定传入的值 | 个数必须一致,顺序无所谓 |
| 默认参数 | 定义函数时提前设置默认值 | 用户传参则用新值,不传则用默认值 |
可变参数 *args | 以元组形式接收任意多个位置参数 | 可以接收任意数量的位置参数 |
可变参数 **kwargs | 以字典形式接收任意多个关键字参数 | 可以接收任意数量的关键字参数 |
🧑💻 综合代码示例
# 1. 定义函数
def show1(name, age, weight):
print(f"姓名:{name},年龄{age}岁,体重:{weight}kg")
def show2(name='张三', age=18, weight=66):
print(f"姓名:{name},年龄{age}岁,体重:{weight}kg")
def show3(*args):
print(args, type(args))
def show4(**kwargs):
print(kwargs, type(kwargs))
def show5(*args, **kwargs):
print("位置参数:", args)
print("关键字参数:", kwargs)
# 2. 调用函数
if __name__ == '__main__':
# 位置传参
show1('张三', 18, 66) # 姓名:张三,年龄18岁,体重:66kg
# 关键字传参
show1(name='张三', age=18, weight=66) # 姓名:张三,年龄18岁,体重:66kg
# 默认参数
show2() # 姓名:张三,年龄18岁,体重:66kg
show2('李四', 20, 70) # 姓名:李四,年龄20岁,体重:70kg
# 可变参数 *args
show3(1, 2, 3) # (1, 2, 3) <class 'tuple'>
# 可变参数 **kwargs
show4(a=1, b=2, c=3) # {'a': 1, 'b': 2, 'c': 3} <class 'dict'>
# 组合使用
show5(1, 2, 3, a=4, b=5, c=6)
# 位置参数: (1, 2, 3)
# 关键字参数: {'a': 4, 'b': 5, 'c': 6}
二、文件操作
1. 文件操作的两种方式
需求: 把当前目录下的test.txt读取到程序中,打印内容
方式1: 原始方式 必须手动关闭,否则浪费资源
# 打开文件
f = open('test.txt', mode='r', encoding='utf8')
# 读文件
data = f.read()
print(data)
# 关闭文件(节省资源)
f.close()
方式2: with方式(推荐) 自动关闭,无需手动
with open('test.txt', mode='r', encoding='utf8') as f:
# 读文件
data = f.read()
print(data)
2. 文件备案
需求: 当前目录中的文件,图片,视频,音频等做个备份
| 模式 | 说明 | 用途 |
|---|---|---|
r | 读取文本文件 | 读 .txt 等文本文件 |
w | 覆盖写数据到文本文件 | 写文本文件(覆盖原内容) |
a | 追加写数据到文本文件 | 文本末尾追加内容 |
rb | 二进制读取文件 ✅ | 读图片、视频、音频等 |
wb | 二进制覆盖写数据到文件 ✅ | 写二进制文件(覆盖原内容) |
ab | 二进制追加写数据到文件 ✅ | 二进制文件末尾追加 |
💡 推荐使用二进制模式
rb/wb:适用于任何文件类型(图片、视频、音频、文本等),通用性最强。
方式1: 原始方式 必须手动关闭,否则浪费资源
# 打开文件
f_in = open('hm.jpg', mode='rb')
f_out = open('hm[备份1].jpg', mode='wb')
# 读写文件
data = f_in.read()
f_out.write(data)
print('文件备份成功!')
# 关闭文件(节省资源)
f_out.close()
f_in.close()
⚠️ 缺点:必须手动
close()关闭文件,容易忘记导致资源浪费。
方式2: with方式(推荐) 自动关闭,无需手动
with open('hm.jpg', mode='rb') as f_in:
with open('hm[备份2].jpg', mode='wb') as f_out:
# 读写文件
data = f_in.read()
f_out.write(data)
💡 推荐使用 with 方式:自动关闭文件,代码更安全、更简洁。
三、模块和包
1. 模块概述
模块:符合标识符命名规则的 .py 文件,就是 Python 模块。
标识符命名规则:
| 规则 | 说明 |
|---|---|
| 组成 | 只能有字母、数字、下划线、汉字 |
| 注意 | 不能以数字开头,不能是关键字,严格区分大小写,不建议用汉字 |
2. 自定义模块
自定义模块很简单:创建一个符合标识符命名规则的 .py 文件,里面定义函数或类即可。
示例:创建一个名为 my_module1.py 的文件
3. 导入模块的两种方式
方式1: import 模块名(推荐)
import my_module1
my_module1.show()
方式2: from 模块名 import 功能
from my_module2 import show
show()
4. 导入模块的进阶用法
方式1: 给模块起别名
import my_module1 as m1
m1.show()
方式2: 给功能起别名
from my_module2 import show as show2
show2()
方式3: 导入模块中的所有功能(不推荐 ❌)
from my_module1 import *
show()
四、面向对象基础
1. 类的基本结构
class Student(object):
# __init__():初始化对象的属性(重点)
def __init__(self, name, age):
# self 代表对象自己,谁调用当前方法,self 就是谁!
self.name = name
self.age = age
# __str__():返回打印对象的内容(了解)
def __str__(self):
return f"姓名:{self.name},年龄:{self.age}"
# __del__():对象删除时自动调用(了解)
def __del__(self):
print(f"{self.name}对象被删除了")
# 自定义方法
def study(self):
print('好好学习,天天向上')
# 创建对象(自动调用 __init__())
zs = Student('张三', 18)
ls = Student('李四', 28)
# 打印对象(自动调用 __str__())
print(zs) # 姓名:张三,年龄:18
print(ls) # 姓名:李四,年龄:28
# 调用属性和方法
print(zs.name)
zs.study()
print(ls.name)
ls.study()
# 程序结束时,GC 垃圾回收器自动删除对象,调用 __del__()
2. 三大方法对比
| 方法 | 触发时机 | 作用 | 掌握程度 |
|---|---|---|---|
__init__() | 创建对象时自动调用 | 初始化对象的属性 | ⭐⭐⭐⭐⭐ 重点 |
__str__() | print(对象) 时调用 | 返回对象的字符串描述 | ⭐⭐⭐ 了解 |
__del__() | 对象被删除时自动调用 | 释放资源、清理工作 | ⭐⭐ 了解 |
3. 继承
继承:子类可以继承父类的属性和方法,实现代码复用。
3.1 单继承
# 父类(基类)
class Animal(object):
def __init__(self, name):
self.name = name
def jiao(self):
print(f'{self.name}会叫')
# 子类(派生类),继承 Animal
class Dog(Animal):
# 重写父类方法,加入自己特有操作
def jiao(self):
print(f'{self.name}会汪汪叫')
class Cat(Animal):
def jiao(self):
print(f'{self.name}会喵喵叫')
# 创建对象
a = Animal("动物")
d = Dog('旺财狗')
c = Cat('招财猫')
a.jiao() # 动物会叫
d.jiao() # 旺财狗会汪汪叫
c.jiao() # 招财猫会喵喵叫
# 查看继承关系(调用方法顺序)
print(Dog.mro())
print(Cat.mro())
3.2 多继承
class Father(object):
def skill(self):
print('生活中各种技能')
class HM(object):
def skill(self):
print('AI大模型的技能')
# 多继承:继承多个父类
class Student(Father, HM):
def skill(self):
# 调用父类的同名方法
Father.skill(self)
HM.skill(self)
s = Student()
s.skill() # 如果两个父类方法重名,优先使用第一个父类的
# 查看方法查找顺序(深度优先,从左到右)
print(Student.mro())
print(Student.__mro__)
多继承方法查找顺序:Student → Father → HM → object
3.3 继承总结
| 概念 | 说明 |
|---|---|
| 单继承 | 一个子类继承一个父类 |
| 多继承 | 一个子类继承多个父类 |
| 重写 | 子类重新定义父类的方法 |
mro() | 查看方法的调用顺序 |
4. 多态
多态:同一个方法在不同对象上有不同的表现形式。
class Animal(object):
def __init__(self, name):
self.name = name
def jiao(self):
print(f'{self.name}会叫')
class Dog():
def __init__(self, name):
self.name = name
def jiao(self):
print(f'{self.name}会汪汪叫')
class Cat():
def __init__(self, name):
self.name = name
def jiao(self):
print(f'{self.name}会喵喵叫')
# 公共的 API,传入动物类型对象,调用叫方法
def animal_jiao(animal): # Python 是动态类型,不限制参数类型
animal.jiao()
# 创建对象,传入 animal_jiao 方法中
d = Dog('旺财狗')
c = Cat('招财猫')
animal_jiao(d) # 旺财狗会汪汪叫
animal_jiao(c) # 招财猫会喵喵叫
💡 多态的好处:同一个函数
animal_jiao()可以处理不同类型的对象,只要它们都有jiao()方法。
5. Python 动态类型
# 动态类型:变量可以随时改变类型
a = 10 # 此处 a 是整数类型
print(a)
a = "abc" # 此处 a 变成字符串类型
print(a)
💡 静态类型 vs 动态类型:
- 静态类型(如 Java):变量类型一旦确定不能改变,编译时检查
- 动态类型(如 Python):变量类型可以随时改变,运行时确定
6. 总结对比
| 概念 | 说明 |
|---|---|
| 类 | 对一类事物的抽象描述(图纸) |
| 对象 | 根据类创建的具体实例(产品) |
self | 代表当前对象本身 |
| 封装 | 将数据和方法封装在类中 |
| 继承 | 子类继承父类的属性和方法 |
| 重写 | 子类重新定义父类的方法 |
| 多态 | 同一个方法在不同对象上有不同表现 |