Python3基础:进阶基础,筑牢编程底层能力

10 阅读27分钟

第六阶段:进阶基础,筑牢编程底层能力

😄生命不息,写作不止

🔥 继续踏上学习之路,学之分享笔记

👊 总有一天我也能像各位大佬一样

🏆 博客首页   @怒放吧德德  To记录领地 @一个有梦有戏的人

🌝分享学习心得,欢迎指正,大家一起学习成长!

🔥豆包AI

转发请携带作者信息  @怒放吧德德(掘金) @一个有梦有戏的人(CSDN)

前言

在第五阶段,我们吃透了函数基础的核心知识点——从函数的定义与调用,到参数、返回值、局部与全局变量,再到匿名函数、函数嵌套与递归,我们终于摆脱了“零散代码”的困境,实现了代码的复用与模块化。

而第六阶段我们要攻克的「进阶基础」,是Python编程从“会用”走向“活用”的关键一步,更是后续学习复杂项目、框架(如Django、PyTorch)的核心基石。这一阶段,我们将重点学习四大核心内容:模块与包(实现代码的规模化复用)、文件操作(实现数据的持久化存储)、异常处理(让代码更健壮、容错性更强)、面向对象基础(解锁更灵活的编程思维)。

本阶段的学习难度相较于前五个阶段略有提升,核心目标不再是“记住语法”,而是“理解逻辑、灵活运用”。全程将延续“知识点解析+可运行代码+避坑技巧”的模式,贴合新手学习节奏,每个代码示例都可直接复制运行,每个知识点都搭配通俗解读,跟着敲代码、练案例,就能轻松掌握进阶基础的核心能力,稳步向“合格的Python初学者”迈进~

1 模块与包:实现代码规模化复用,告别“复制粘贴”

在第五阶段,我们用函数实现了“代码片段的复用”,但当项目越来越大、函数越来越多,我们会发现:大量函数堆砌在一个文件中,不仅难以查找、维护,还容易出现命名冲突。而「模块与包」,就是为解决这个问题而生的——它们能帮我们将代码按功能分类、组织,实现“跨文件复用”,让代码结构更清晰、更具可扩展性。

简单来说:模块(Module) 是一个包含Python代码的 .py 文件(比如my_module.py),里面可以定义函数、类、变量;包(Package) 是一个包含多个模块(.py文件)的目录,目录下必须有一个 __init__.py 文件(可为空),用于标识这个目录是一个Python包。

1.1 模块的使用:import导入(核心操作)

Python提供了多种导入模块的方式,核心是使用 import 关键字,新手重点掌握4种常用方式,结合示例理解,可直接复制运行。

# 方式1:导入整个模块(最基础)
# 语法:import 模块名
import random  # 导入Python内置的随机数模块(无需自己创建)

# 使用模块中的函数/变量:模块名.函数名() / 模块名.变量名
print("随机整数(1-10):", random.randint(1, 10))
print("随机浮点数(0-1):", random.random())

# 方式2:导入模块并指定别名(简化调用,常用)
# 语法:import 模块名 as 别名
import datetime as dt  # 导入内置日期时间模块,别名dt

# 使用别名调用,更简洁
now = dt.datetime.now()
print("当前时间:", now.strftime("%Y-%m-%d %H:%M:%S"))

# 方式3:从模块中导入指定的函数/变量(推荐,按需导入)
# 语法:from 模块名 import 函数名1, 函数名2, 变量名
from math import pi, sqrt  # 从内置数学模块导入pi(圆周率)和sqrt(开平方)

print("圆周率pi:", pi)
print("9的平方根:", sqrt(9))  # 输出3.0

# 方式4:从模块中导入所有内容(不推荐,易出现命名冲突)
# 语法:from 模块名 import *
from random import *

print("随机选择列表元素:", choice([1, 2, 3, 4, 5]))
# 注意:这种方式会导入模块中所有可导入的内容,若与自身定义的函数/变量同名,会覆盖

1.2 自定义模块:自己写模块,实现跨文件复用

除了使用Python内置模块,我们还可以自己编写模块(.py文件),将自己定义的函数、类、变量放入其中,供其他文件导入使用——这是实际编程中常用的技巧,实现代码的跨文件复用。

步骤:① 创建一个 .py 文件(模块文件),编写代码(函数、类等);② 在另一个文件中,用import导入这个模块,即可使用其中的内容。

# 第一步:创建自定义模块(文件名:my_module.py,与当前运行文件放在同一目录下)
# ------------------ my_module.py 内容 ------------------
# 定义一个计算两数之和的函数
def add(a, b):
    return a + b

# 定义一个计算两数之差的函数
def subtract(a, b):
    return a - b

# 定义一个全局变量
PI = 3.1415926

# 模块自测:当模块被直接运行时,执行以下代码(导入时不执行)
# 控制模块执行(入口点)
if __name__ == "__main__":
    print("模块自测:3+5 =", add(3, 5))
    print("模块自测:10-4 =", subtract(10, 4))
# ------------------------------------------------------

# 第二步:在当前文件(比如main.py)中导入自定义模块,使用其中的内容
# 导入自定义模块
import my_module

# 使用模块中的函数
print("3+5 =", my_module.add(3, 5))  # 输出8
print("10-4 =", my_module.subtract(10, 4))  # 输出6

# 使用模块中的变量
print("圆周率(自定义模块):", my_module.PI)  # 输出3.1415926

# 也可以用别名导入
import my_module as mm
print("5+8 =", mm.add(5, 8))  # 输出13

# 也可以按需导入
from my_module import add, PI
print("2+7 =", add(2, 7))  # 输出9

关键知识点:if __name__ == "__main__": —— 每个模块都有一个 __name__ 属性,当模块被直接运行时,__name__ 的值为 "__main__",此时会执行该判断下的代码(用于模块自测);当模块被导入时,__name__ 的值为模块名,该判断下的代码不会执行。

类似 Java 的 main 方法

public class MyClass {

public static void main(String[] args) {

    // 入口点

}

}

1.3 包的使用:组织多个模块,实现功能分类

当自定义模块越来越多(比如10个、20个),我们可以用“包”将它们按功能分类(比如数据处理相关的模块放在一个包,工具类模块放在另一个包)。包的核心是“目录+init.py文件”。

示例(包的创建与导入):

# 第一步:创建包(目录结构如下)
# my_package/  # 包目录
#     __init__.py  # 必须有,可为空文件(标识该目录是Python包)
#     calc_module.py  # 模块1:计算相关函数
#     tool_module.py  # 模块2:工具相关函数

# 第二步:编写包内模块的代码
# ------------------ calc_module.py 内容 ------------------
def multiply(a, b):
    return a * b

def divide(a, b):
    return a / b if b != 0 else "除数不能为0"
# ------------------------------------------------------

# ------------------ tool_module.py 内容 ------------------
def print_info(info):
    print(f"【信息】:{info}")

def is_positive(num):
    return num > 0
# ------------------------------------------------------

# 第三步:导入包中的模块,使用其中的内容
# 方式1:导入包中的某个模块
from my_package import calc_module, tool_module

print("3×5 =", calc_module.multiply(3, 5))  # 输出15
tool_module.print_info("Python包的使用示例")  # 输出【信息】:Python包的使用示例

# 方式2:导入包中模块的指定函数
from my_package.calc_module import multiply
from my_package.tool_module import is_positive

print("4×6 =", multiply(4, 6))  # 输出24
print("5是否为正数:", is_positive(5))  # 输出True

# 方式3:给包/模块指定别名
from my_package import tool_module as tm
tm.print_info("别名导入示例")  # 输出【信息】:别名导入示例

1.4 常用内置模块(新手必学,直接可用)

Python内置了大量实用模块,无需自己编写,导入即可使用,新手重点掌握以下5个,能解决80%的基础编程场景:

# 1. random:随机数模块(常用)
import random
print("随机整数(1-100):", random.randint(1, 100))
print("随机选择元素:", random.choice(["苹果", "香蕉", "橙子"]))
print("打乱列表:", random.shuffle([1, 2, 3, 4, 5]))  # 原地打乱

# 2. datetime:日期时间模块(常用)
import datetime
now = datetime.datetime.now()  # 获取当前时间
print("当前时间:", now)
print("格式化时间(年-月-日):", now.strftime("%Y-%m-%d"))
print("3天后的日期:", now + datetime.timedelta(days=3))

# 3. math:数学模块(常用)
import math
print("圆周率:", math.pi)
print("16的平方根:", math.sqrt(16))  # 4.0
print("绝对值:", math.fabs(-5.2))  # 5.2
print("正弦值(弧度):", math.sin(math.pi/2))  # 1.0

# 4. os:操作系统相关模块(文件路径、目录操作)
import os
print("当前目录路径:", os.getcwd())  # 获取当前工作目录
print("当前目录下的文件:", os.listdir())  # 列出当前目录下所有文件/目录
# os.mkdir("test_dir")  # 创建一个名为test_dir的目录(需确保目录不存在)

# 5. sys:系统相关模块(简单了解)
import sys
print("Python版本:", sys.version)  # 查看Python版本
print("命令行参数:", sys.argv)  # 查看命令行参数

1.5 新手避坑指南(模块与包必看)

  • 避坑1:自定义模块名、包名,不要与Python内置模块名重名(比如不要命名为random.py、math.py),否则会覆盖内置模块,导致报错;
  • 避坑2:导入模块时,若模块不在当前目录下,会报错——解决方案:将模块所在目录添加到Python的搜索路径,或把模块放在当前运行文件同一目录;
  • 避坑3:包目录下必须有 __init__.py 文件(可为空),否则Python不会将其识别为包,无法导入;
  • 避坑4:尽量避免使用 from 模块名 import *,容易出现命名冲突,推荐按需导入(from 模块名 import 函数名);
  • 避坑5:if __name__ == "__main__": 仅用于模块自测,导入模块时不会执行,不要依赖它实现核心功能。

2 文件操作:实现数据持久化,让数据“存得住”

在前面的学习中,我们处理的数据(比如列表、字典、变量),都是“临时数据”——程序运行结束后,数据就会被销毁。而实际编程中,我们常常需要将数据“保存到文件中”(比如用户信息、日志、数据结果),也需要从文件中“读取数据”——这就是「文件操作」的核心作用:实现数据的持久化存储。

Python中文件操作的核心是 open() 函数,用于打开文件,然后通过相关方法实现读取、写入、关闭,重点掌握“打开→操作→关闭”的流程,以及更简洁、安全的 with 上下文管理器。

2.1 文件操作的核心流程:打开→读取/写入→关闭

文件操作必须遵循“打开文件→操作文件(读/写)→关闭文件”的流程——关闭文件是重中之重,若忘记关闭,会导致文件资源泄露、文件被占用(无法再次打开),甚至数据丢失。

# 核心语法:open(文件路径, 打开模式, encoding=编码格式)
# 1. 打开文件(以读取模式打开,encoding='utf-8'避免中文乱码)
# 注意:若文件不存在,r模式会报错
file = open("test.txt", "r", encoding="utf-8")

# 2. 读取文件内容(三种常用方式)
# 方式1:read():读取全部内容,返回字符串
content1 = file.read()
print("read()读取全部内容:", content1)

# 方式2:readline():读取一行内容,每次调用读取下一行
file.seek(0)  # 重置文件指针到开头(否则会从上次读取的位置继续)
content2 = file.readline()
print("readline()读取第一行:", content2)
content3 = file.readline()
print("readline()读取第二行:", content3)

# 方式3:readlines():读取所有行,返回列表(每行为一个元素)
file.seek(0)
content4 = file.readlines()
print("readlines()读取所有行:", content4)  # 输出:['第一行内容\n', '第二行内容\n', '第三行内容']

# 3. 关闭文件(必须执行,否则会导致资源泄露)
file.close()

# 补充:写入文件(w模式:覆盖写入,若文件不存在则创建)
file2 = open("test.txt", "w", encoding="utf-8")
file2.write("这是覆盖写入的内容\n")  # 写入字符串
file2.write("这是第二行写入的内容")
file2.close()  # 关闭文件后,写入内容才会生效

# 补充:追加写入(a模式:在文件末尾追加,不覆盖原有内容)
file3 = open("test.txt", "a", encoding="utf-8")
file3.write("\n这是追加的内容")
file3.close()

2.2 关键知识点:打开模式(必记)

open()函数的第二个参数“打开模式”,决定了文件操作的类型(读/写/追加),新手重点记以下6种常用模式:

# 常用打开模式(核心必记)
# 1. r:只读模式(默认),若文件不存在则报错,只能读取,不能写入
# 2. w:覆盖写入模式,若文件不存在则创建,若文件存在则覆盖原有内容
# 3. a:追加写入模式,若文件不存在则创建,写入内容追加到文件末尾
# 4. r+:读写模式,既能读取,也能写入(不会覆盖原有内容,从指针位置开始写入)
# 5. w+:读写模式,覆盖写入(若文件不存在则创建),既能写也能读
# 6. a+:读写模式,追加写入,既能写也能读

# 示例:r+模式(读写)
file = open("test.txt", "r+", encoding="utf-8")
content = file.read()
print("读取内容:", content)
file.write("\nr+模式写入的内容")  # 在文件末尾写入(因为指针在读取后到了末尾)
file.close()

# 示例:w+模式(覆盖读写)
file = open("test2.txt", "w+", encoding="utf-8")
file.write("w+模式覆盖写入的内容")
file.seek(0)  # 重置指针到开头,否则读取不到内容
content = file.read()
print("w+模式读取内容:", content)
file.close()

2.3 with上下文管理器:自动关闭文件,更简洁、更安全

新手最容易踩的坑:忘记关闭文件(file.close()),导致文件资源泄露。而 with 上下文管理器,能帮我们自动关闭文件——进入with代码块时,自动打开文件;退出with代码块时,自动关闭文件(无论代码是否报错),无需手动调用close(),是文件操作的“首选方式”。

# with上下文管理器(读取文件,推荐用法)
with open("test.txt", "r", encoding="utf-8") as file:
    # 缩进内的代码的是文件操作范围,退出缩进后,文件自动关闭
    content = file.read()
    print("with读取文件:", content)
# 退出with后,文件已自动关闭,无需手动close()
# print(file.read())  # 报错:文件已关闭,无法读取

# with写入文件(覆盖写入)
with open("test3.txt", "w", encoding="utf-8") as file:
    file.write("with模式写入的内容\n")
    file.write("自动关闭文件,无需手动操作")

# with追加写入
with open("test3.txt", "a", encoding="utf-8") as file:
    file.write("\n追加写入的内容")

# with同时打开多个文件(比如复制文件内容)
with open("test3.txt", "r", encoding="utf-8") as read_file, \
     open("test4.txt", "w", encoding="utf-8") as write_file:
    # 读取test3.txt的内容,写入test4.txt(实现文件复制)
    content = read_file.read()
    write_file.write(content)
print("文件复制完成!")

核心优势:用with操作文件,既简洁(少写close()),又安全(即使代码块中报错,也会自动关闭文件),新手全程优先使用这种方式。

2.4 文件路径:找到文件的“准确位置”

文件操作时,若文件不在当前运行目录下,直接写文件名会报错——此时需要指定“文件路径”,文件路径分为两种:相对路径和绝对路径。

# 1. 相对路径(常用):以当前运行文件的目录为基准,查找文件
# 示例1:文件在当前目录下(直接写文件名)
with open("test.txt", "r", encoding="utf-8") as file:
    pass

# 示例2:文件在当前目录的子目录下(比如data目录下)
# 目录结构:当前文件 → data → test5.txt
with open("data/test5.txt", "r", encoding="utf-8") as file:
    pass

# 示例3:文件在当前目录的上级目录下
# 目录结构:上级目录 → 当前文件目录 → 当前文件;上级目录 → test6.txt
with open("../test6.txt", "r", encoding="utf-8") as file:
    pass  # ../ 表示上级目录

# 2. 绝对路径(精准,不会出错):从电脑的根目录开始,指定完整路径
# Windows系统(注意路径中的反斜杠用\\,或用正斜杠/)
with open("D:\\Python\\test7.txt", "r", encoding="utf-8") as file:
    pass
# 或
with open("D:/Python/test7.txt", "r", encoding="utf-8") as file:
    pass

# Mac/Linux系统(路径用正斜杠/)
with open("/Users/xxx/Python/test7.txt", "r", encoding="utf-8") as file:
    pass

# 补充:用os模块获取当前路径,避免路径错误(推荐)
import os
# 获取当前运行文件的目录路径
current_dir = os.path.dirname(os.path.abspath(__file__))
# 拼接文件路径(兼容Windows和Mac/Linux)
file_path = os.path.join(current_dir, "test.txt")
# 使用拼接后的路径打开文件
with open(file_path, "r", encoding="utf-8") as file:
    content = file.read()
    print("通过os模块拼接路径读取:", content)

2.5 新手避坑指南(文件操作必看)

  • 避坑1:操作中文文件时,必须指定 encoding="utf-8",否则会出现中文乱码或报错;
  • 避坑2:忘记关闭文件——优先使用with上下文管理器,自动关闭文件,无需手动操作;
  • 避坑3:w模式是“覆盖写入”,慎用!一旦使用w模式打开已有文件,原有内容会被全部清空,无法恢复;
  • 避坑4:读取文件后,文件指针会移动到读取结束的位置,再次读取会读取不到内容,需用 file.seek(0) 重置指针;
  • 避坑5:文件路径错误——若文件不在当前目录,需指定相对路径或绝对路径,推荐用os模块拼接路径,避免手动写路径出错;
  • 避坑6:with代码块外,无法访问文件对象(文件已自动关闭),不要在with外操作文件。

3 异常处理:让代码更健壮,从容应对“报错”

在前面的学习中,我们写的代码一旦出现错误(比如文件不存在、除以零、输入错误),程序就会直接崩溃,抛出异常(报错信息)。而「异常处理」,就是通过特定的语法,捕获程序运行中的异常,处理异常(比如给出友好提示),让程序不会崩溃,继续执行——这是编写“健壮代码”的核心技能。

Python中异常处理的核心语法是try-except,配合 finallyraise,实现完整的异常处理逻辑。

3.1 基础异常处理:try-except(捕获异常)

语法逻辑:尝试执行try代码块中的代码,若出现异常,就执行except代码块中的代码(处理异常);若没有异常,就跳过except代码块,执行后续代码。

# 示例1:捕获所有异常(简单,但不推荐,无法定位具体异常类型)
try:
    # 尝试执行的代码(可能会报错的代码)
    num1 = int(input("请输入第一个数字:"))
    num2 = int(input("请输入第二个数字:"))
    result = num1 / num2
    print(f"结果:{num1} ÷ {num2} = {result}")
except:
    # 出现异常时,执行的代码(处理异常)
    print("出错了!请输入正确的数字,且除数不能为0!")

# 示例2:捕获指定类型的异常(推荐,能精准处理不同异常)
try:
    num1 = int(input("请输入第一个数字:"))
    num2 = int(input("请输入第二个数字:"))
    result = num1 / num2
    print(f"结果:{num1} ÷ {num2} = {result}")
except ValueError:
    # 捕获“值错误”(比如输入的不是数字)
    print("出错了!请输入整数类型的数字!")
except ZeroDivisionError:
    # 捕获“除以零错误”
    print("出错了!除数不能为0,请重新输入!")

# 示例3:捕获多个指定异常,统一处理
try:
    # 尝试打开文件读取
    with open("test_not_exist.txt", "r", encoding="utf-8") as file:
        content = file.read()
except (FileNotFoundError, UnicodeDecodeError):
    # 捕获“文件不存在”或“编码错误”
    print("出错了!文件不存在或编码格式错误!")

# 示例4:捕获异常,并获取异常信息(便于调试)
try:
    num1 = int(input("请输入第一个数字:"))
    num2 = int(input("请输入第二个数字:"))
    result = num1 / num2
except ValueError as e:
    # e 是异常对象,存储异常信息
    print(f"值错误:{e}")  # 输出具体的错误信息,比如:invalid literal for int() with base 10: 'abc'
except ZeroDivisionError as e:
    print(f"除以零错误:{e}")  # 输出:division by zero

3.2 finally语句:无论是否异常,都必须执行

finally 语句用于定义“无论是否出现异常,都必须执行的代码”,常用场景:资源清理(比如关闭文件、断开数据库连接)——即使try代码块报错,finally代码块也会执行。

# 示例1:finally基本用法
try:
    num1 = int(input("请输入第一个数字:"))
    num2 = int(input("请输入第二个数字:"))
    result = num1 / num2
    print(f"结果:{result}")
except ZeroDivisionError:
    print("除数不能为0!")
finally:
    # 无论是否异常,都会执行
    print("程序执行完毕(无论成功还是失败)")

# 示例2:finally用于资源清理(即使报错,也会关闭文件)
file = None
try:
    file = open("test.txt", "r", encoding="utf-8")
    content = file.read()
    print(content)
except FileNotFoundError:
    print("文件不存在!")
finally:
    # 无论是否异常,都关闭文件(避免资源泄露)
    if file:  # 判断文件是否成功打开
        file.close()
        print("文件已关闭")

# 补充:with上下文管理器已自动处理关闭文件,无需用finally,但其他资源清理可使用
try:
    with open("test.txt", "r", encoding="utf-8") as file:
        content = file.read()
except FileNotFoundError:
    print("文件不存在!")
finally:
    print("文件操作流程结束")

3.3 raise语句:主动抛出异常,控制程序逻辑

raise 语句用于“主动抛出异常”——当我们检测到不符合预期的条件时,主动让程序抛出异常,中断执行,或让上层代码处理异常。

# 示例1:主动抛出异常(基础用法)
def check_age(age):
    # 检测年龄是否合法,不合法则主动抛出异常
    if age < 0 or age > 120:
        # 主动抛出ValueError异常,并指定异常信息
        raise ValueError("年龄不合法!年龄必须在0-120之间")
    print(f"年龄合法:{age}岁")

# 调用函数,捕获主动抛出的异常
try:
    check_age(-5)  # 不符合条件,主动抛出异常
except ValueError as e:
    print(f"捕获异常:{e}")  # 输出:捕获异常:年龄不合法!年龄必须在0-120之间

try:
    check_age(25)  # 合法,正常执行
except ValueError as e:
    print(f"捕获异常:{e}")

# 示例2:结合函数,主动抛出异常,控制逻辑
def login(username, password):
    # 模拟登录验证,若用户名或密码为空,主动抛出异常
    if not username:
        raise Exception("用户名不能为空!")
    if not password:
        raise Exception("密码不能为空!")
    print("登录验证通过,正在进入系统...")

# 调用登录函数
try:
    login("", "123456")
except Exception as e:
    print(f"登录失败:{e}")  # 输出:登录失败:用户名不能为空!

3.4 新手避坑指南(异常处理必看)

  • 避坑1:不要滥用 except: 捕获所有异常——无法定位具体的错误类型,不利于调试,推荐捕获指定类型的异常;
  • 避坑2:finally代码块中不要写return语句——会覆盖try/except中的return值,导致异常信息丢失;
  • 避坑3:raise语句抛出的异常,必须有对应的except捕获,否则程序依然会崩溃;
  • 避坑4:异常处理的核心是“处理异常”,不是“隐藏异常”——不要只捕获异常,不给出任何提示,否则会导致程序异常却无法排查;
  • 避坑5:资源清理(如关闭文件),优先用with上下文管理器,若手动打开文件,需在finally中关闭,避免资源泄露。

4 面向对象基础:解锁更灵活的编程思维

在前面的学习中,我们用“面向过程”的思维编写代码——按步骤拆解问题,一步一步执行(比如先定义函数,再调用函数,按顺序执行逻辑)。而「面向对象」,是一种更灵活、更贴近现实世界的编程思维——将现实世界中的事物(比如人、汽车、学生)抽象成“类”,用类创建“对象”,通过对象的属性和方法实现功能。

面向对象的核心概念:类(Class)对象(Object)。类是“模板”(比如“学生”类),对象是“模板的实例”(比如“张三”“李四”这两个具体的学生);类中包含“属性”(事物的特征,比如学生的姓名、年龄)和“方法”(事物的行为,比如学生的学习、吃饭)。

4.1 类与对象:核心概念与创建

Python中用 class 关键字定义类,类名通常采用“大驼峰命名法”(首字母大写,多个单词首字母均大写,比如Student、Person);通过“类名()”创建对象(实例化对象)。

# 示例1:定义一个简单的类(Student类)
class Student:
    # 类的属性(学生的特征):可以直接定义,也可以通过初始化方法定义
    # 类属性:所有对象共享的属性(比如学生的学校)
    school = "北京大学"

    # 类的方法(学生的行为):定义在类中的函数,第一个参数必须是self
    def study(self):
        # self 代表当前对象(调用该方法的对象),必须作为第一个参数
        print(f"{self.name} 正在学习Python基础!")

    def eat(self):
        print(f"{self.name} 正在吃饭!")

# 示例2:创建对象(实例化对象)
# 创建第一个对象(张三)
stu1 = Student()
# 给对象添加实例属性(每个对象独有的属性,比如姓名、年龄)
stu1.name = "张三"
stu1.age = 18
# 调用对象的方法
stu1.study()  # 输出:张三 正在学习Python基础!
stu1.eat()    # 输出:张三 正在吃饭!
# 访问对象的属性(实例属性和类属性)
print(f"姓名:{stu1.name},年龄:{stu1.age},学校:{stu1.school}")

# 创建第二个对象(李四)
stu2 = Student()
stu2.name = "李四"
stu2.age = 19
stu2.study()  # 输出:李四 正在学习Python基础!
print(f"姓名:{stu2.name},年龄:{stu2.age},学校:{stu2.school}")

# 访问类属性(通过类名访问,所有对象共享)
print("类属性(学校):", Student.school)

关键知识点:self —— 类中定义的方法,第一个参数必须是self,self代表“当前调用方法的对象”,通过self可以访问对象的属性和其他方法,调用方法时,无需手动传递self参数(Python会自动传递)。

4.2 __init__初始化方法:创建对象时自动初始化属性

前面的示例中,我们创建对象后,需要手动给对象添加实例属性(stu1.name = "张三"),非常繁琐。而 __init__ 方法(初始化方法),是类的特殊方法,创建对象时会自动调用,用于初始化对象的属性——相当于“对象的构造函数”,能帮我们简化对象的创建过程。

重点:__init__ 前后各有两个下划线(双下划线),是Python的特殊方法命名规范;第一个参数必须是self,后续参数用于接收创建对象时传递的属性值。

# 示例:定义带有__init__初始化方法的Student类(推荐用法)
class Student:
    # 类属性(所有对象共享)
    school = "北京大学"

    # __init__初始化方法:创建对象时自动调用,初始化实例属性
    # self:必须有,代表当前对象
    # name、age:接收创建对象时传递的参数,作为实例属性
    def __init__(self, name, age):
        # 给当前对象添加实例属性,绑定参数值
        self.name = name
        self.age = age
        # 可以在__init__中添加额外的初始化逻辑
        print(f"创建学生对象:{self.name}{self.age}岁")

    # 类中的方法
    def study(self):
        print(f"{self.name}{self.age}岁)正在学习Python第六阶段内容!")

    def introduce(self):
        # 访问实例属性和类属性
        print(f"大家好,我是{self.name},今年{self.age}岁,来自{self.school}")

# 创建对象:创建时直接传递参数,__init__自动调用,初始化属性
stu1 = Student("张三", 18)  # 输出:创建学生对象:张三,18岁
stu2 = Student("李四", 19)  # 输出:创建学生对象:李四,19岁

# 直接访问对象的实例属性(无需手动添加)
print(f"stu1:{stu1.name}{stu1.age}岁")
print(f"stu2:{stu2.name}{stu2.age}岁")

# 调用对象的方法
stu1.study()  # 输出:张三(18岁)正在学习Python第六阶段内容!
stu2.introduce()  # 输出:大家好,我是李四,今年19岁,来自北京大学

# 补充:修改实例属性和类属性
stu1.age = 20  # 修改stu1的实例属性(仅影响stu1)
print(f"张三修改后的年龄:{stu1.age}岁")
Student.school = "清华大学"  # 修改类属性(所有对象共享,都会影响)
print(f"stu1的学校:{stu1.school}")
print(f"stu2的学校:{stu2.school}")

关键提醒:__init__ 方法不是“构造函数”,Python中对象的创建由 __new__ 方法完成,__init__ 仅用于对创建好的对象进行初始化操作,新手无需深究 __new__ 方法,重点掌握__init__ 的用法即可。

构造方法,类似 Java:

public class MyClass {

public MyClass() {  // 构造方法

    // 初始化代码

}

}

4.3 类的属性与方法:详细解析

类中包含两种核心元素:属性(特征)和方法(行为),按作用范围可分为“类属性/类方法”和“实例属性/实例方法”,新手重点掌握实例属性和实例方法。

# 示例:详细区分实例属性、类属性、实例方法
class Person:
    # 1. 类属性:定义在类中,不在任何方法中,所有对象共享
    species = "人类"  # 所有Person对象的species属性都是“人类”

    # 2. __init__初始化方法:初始化实例属性(每个对象独有)
    def __init__(self, name, age):
        # 实例属性:定义在__init__中,通过self绑定,每个对象独有
        self.name = name
        self.age = age

    # 3. 实例方法:定义在类中,第一个参数是self,只能通过对象调用
    def sleep(self):
        print(f"{self.name}{self.age}岁)正在睡觉")

    # 4. 类方法(简单了解):定义在类中,用@classmethod装饰,第一个参数是cls(代表类)
    @classmethod
    def show_species(cls):
        print(f"物种:{cls.species}")  # 通过cls访问类属性

# 访问类属性(两种方式)
print(Person.species)  # 方式1:通过类名访问(推荐)
p1 = Person("张三", 18)
print(p1.species)      # 方式2:通过对象访问(不推荐,类属性应通过类名访问)

# 访问实例属性(只能通过对象访问)
print(p1.name, p1.age)
# print(Person.name)  # 报错:类不能访问实例属性

# 调用实例方法(只能通过对象访问)
p1.sleep()

# 调用类方法(两种方式)
Person.show_species()  # 方式1:通过类名访问(推荐)
p1.show_species()      # 方式2:通过对象访问

# 补充:修改属性
# 修改类属性(影响所有对象)
Person.species = "智人"
p2 = Person("李四", 19)
print(p1.species)  # 输出:智人
print(p2.species)  # 输出:智人

# 修改实例属性(仅影响当前对象)
p1.age = 20
print(p1.age)  # 输出:20
print(p2.age)  # 输出:19

4.4 新手避坑指南(面向对象基础必看)

  • 避坑1:__init__ 方法前后必须各有两个下划线,少写或多写都会变成普通方法,无法自动调用;
  • 避坑2:类中定义的方法,第一个参数必须是self(实例方法)或cls(类方法),否则调用时会报错;
  • 避坑3:实例属性只能通过对象访问,类不能访问实例属性;类属性可以通过类名或对象访问,但推荐通过类名访问;
  • 避坑4:修改类属性时,必须通过“类名.类属性”修改,通过“对象.类属性”修改,本质是给对象添加一个同名的实例属性,不会修改类属性;
  • 避坑5:不要混淆“类”和“对象”——类是模板,不能直接使用方法/属性(除类方法、类属性),必须创建对象,通过对象使用实例方法和实例属性;
  • 避坑6:__init__ 方法不能有return语句(除非return None),否则会报错。

5 总结

恭喜大家!Python3基础学习第六阶段「进阶基础」的核心内容,到这里就全部梳理完毕了!这一阶段,我们跳出了“基础语法”的范畴,学习了四大核心进阶知识点,每一个都对后续的Python学习至关重要:

  • 模块与包:帮我们组织代码、实现跨文件复用,告别代码堆砌和命名冲突,为编写大型项目打下基础;
  • 文件操作:实现数据的持久化存储,让我们能读取、写入文件,处理实际场景中的数据(如用户信息、日志);
  • 异常处理:让代码更健壮、容错性更强,从容应对程序运行中的错误,避免程序崩溃;
  • 面向对象基础:解锁“面向对象”的编程思维,将现实世界的事物抽象成类和对象,让代码更灵活、更易维护。

第六阶段的学习,难度明显提升——不仅需要记住语法,更需要理解逻辑、转变思维(尤其是面向对象思维,从“面向过程”到“面向对象”的转变,新手可能需要一定时间适应)。对于新手来说,重点注意以下几点:

  1. 模块与包:重点掌握import导入的4种方式、自定义模块的编写与导入,以及常用内置模块的使用,多练习跨文件复用代码;
  2. 文件操作:全程优先使用with上下文管理器,牢记常用打开模式,掌握相对路径和绝对路径的API.

转发请携带作者信息 @怒放吧德德 @一个有梦有戏的人
持续创作很不容易,作者将以尽可能的详细把所学知识分享各位开发者,一起进步一起学习。转载请携带链接,转载到微信公众号请勿选择原创,谢谢!
👍创作不易,如有错误请指正,感谢观看!记得点赞哦!👍
谢谢支持!