零基础学 Python 第15章 | 类与对象:面向对象编程入门

📅 2026/7/19 13:40:26
零基础学 Python 第15章 | 类与对象:面向对象编程入门
本章摘要核心目标掌握用class定义类、创建对象能用面向对象思维组织代码核心知识点class定义类、__init__初始化方法、self参数、实例化、实例属性、实例方法、类属性与实例属性区别实操产出学生信息管理类含自我介绍、及格判断、加分功能前置基础第14章模块与导入、第7章字典、第4-5章函数与循环一、写在前面上一章你学了模块——把代码拆分到不同文件方便管理和复用。但到目前为止你写的所有代码都是面向过程的一步一步告诉计算机先做这个再做那个用函数把重复逻辑封装起来。这种写法没问题但当程序变大、要描述的东西变复杂时你会发现自己一直在跟一堆散乱的变量和函数打交道。比如管理学生信息你需要一个变量存姓名、一个存年龄、一个存成绩再写几个函数来操作这些变量……数据和行为是分开的容易乱。**面向对象编程Object-Oriented Programming(OOP)**的思路完全不同把数据和行为打包到一起形成一个对象。你在 Scratch 里其实早就用过这个思路——每个角色有自己的属性位置、大小、造型和脚本代码积木角色本身就是对象的雏形。这一章我们就从 Scratch 角色出发正式走进 Python 的类与对象。二、什么是类和对象结论类是模板图纸对象是按模板造出来的具体实例。先说一个生活类比。你见过饼干模具吗一个星星形状的模具可以压出无数块星星饼干。模具本身不是饼干但它决定了每一块饼干长什么样。在这里模具 类class定义了有什么属性和能做什么动作饼干 对象object按模具造出来的具体实例每个对象都有自己的属性值再比如汽车图纸和具体的车图纸规定了有颜色、有品牌、有速度但具体每辆车的颜色、品牌、速度各不相同。图纸是类每辆车是对象。2.1 用class定义类Python 用class关键字定义类语法非常简洁# 定义一个最简单的类classDog:pass# pass 是占位符表示什么都不做print(Dog)# class __main__.Dogclass Dog:声明了一个名为Dog的类pass表示类体暂时为空。打印Dog可以看到它是一个类class。2.2 实例化对象有了类就可以造对象了——这叫实例化语法是类名()classDog:pass# 实例化用 Dog 类创建两个对象dog1Dog()dog2Dog()print(dog1)# __main__.Dog object at 0x...print(dog2)# __main__.Dog object at 0x...print(dog1dog2)# False —— 两个不同的对象dog1和dog2都是Dog类的实例但它们是两个独立的对象内存地址不同。就像用同一个模具压出两块饼干虽然形状一样但它们是两块独立的饼干。类名习惯用大驼峰命名法每个单词首字母大写如Student、MyDog、PhoneNumber。这是 Python 社区的约定俗成。三、__init__初始化方法结论__init__是对象创建时自动执行的方法用来给对象设置初始属性。类只定义了有什么但具体每个对象的属性值是多少这就需要__init__方法了。3.1 基本语法__init__init是initialize的缩写是 Python 的特殊方法名字两端各有两个下划线。每次实例化对象时Python 会自动调用它classDog:def__init__(self,name,age):self.namename# 给对象设置 name 属性self.ageage# 给对象设置 age 属性# 实例化时传入参数__init__ 自动接收dog1Dog(旺财,3)dog2Dog(小黑,5)print(dog1.name)# 旺财print(dog1.age)# 3print(dog2.name)# 小黑print(dog2.age)# 5注意看实例化时写的是Dog(旺财, 3)传了两个参数但__init__的参数列表里有三个self, name, age。self不需要你手动传Python 自动帮你填——它就是正在创建的那个对象。3.2__init__执行时机classCat:def__init__(self,name):self.namenameprint(f{self.name}出生了)# 创建对象的瞬间__init__ 自动执行catCat(咪咪)# 输出咪咪 出生了你不需要手动调用__init__它在类名()的那一刻自动执行。就像 Scratch 里角色被添加到舞台时当绿旗被点击积木自动执行一样。四、self参数详解结论self就是当前这个对象自己用self.属性名访问对象的属性用self.方法名()调用对象的方法。self是面向对象里最容易让人困惑的概念但其实你可以这样理解当你叫旺财坐下时“旺财知道你在叫它它自己执行坐下这个动作。self就是那个自己”。4.1self指向当前对象classDog:def__init__(self,name):self.namenamedefbark(self):# 通过 self.name 访问当前对象的 name 属性print(f{self.name}汪汪汪)dog1Dog(旺财)dog2Dog(小黑)dog1.bark()# 旺财 汪汪汪dog2.bark()# 小黑 汪汪汪当dog1.bark()执行时self就是dog1所以self.name是 “旺财”。当dog2.bark()执行时self就是dog2所以self.name是 “小黑”。4.2self不能省略classDog:def__init__(self,name):self.namename# ❌ 错误写法漏掉 self# def bark():# print(f{name} 汪汪汪) # NameError: name name is not defined在实例方法里self必须是第一个参数。虽然调用时你不用手动传但定义时一定要写。Python 靠self知道这个方法要操作哪个对象。4.3 用self在方法间共享属性classDog:def__init__(self,name):self.namename self.energy100# 初始精力值 100defrun(self):self.energy-20# 跑一步消耗 20 精力print(f{self.name}跑了剩余精力{self.energy})defsleep(self):self.energy100# 睡一觉恢复精力print(f{self.name}睡醒了精力恢复到{self.energy})dogDog(旺财)dog.run()# 旺财 跑了剩余精力 80dog.run()# 旺财 跑了剩余精力 60dog.sleep()# 旺财 睡醒了精力恢复到 100self.energy在__init__中创建在run()和sleep()中通过self访问和修改。self让同一个对象的不同方法共享同一份数据。五、实例属性结论实例属性是每个对象各自拥有的数据在__init__中通过self.属性名 值创建。5.1 定义和访问实例属性classStudent:def__init__(self,name,age,score):self.namename# 姓名self.ageage# 年龄self.scorescore# 成绩s1Student(小明,18,85)s2Student(小红,19,92)# 每个对象有自己的属性值print(s1.name,s1.age,s1.score)# 小明 18 85print(s2.name,s2.age,s2.score)# 小红 19 925.2 动态添加实例属性Python 允许在创建对象后动态添加属性其他语言一般不行s1Student(小明,18,85)s1.class_name高三一班# 动态添加只有 s1 有这个属性print(s1.class_name)# 高三一班# print(s2.class_name) # ❌ AttributeError: Student object has no attribute class_name虽然 Python 支持动态添加属性但不推荐这么做。好的习惯是在__init__里把所有属性都定义好让代码清晰可读。5.3 修改实例属性s1Student(小明,18,85)print(s1.score)# 85s1.score90# 直接赋值修改print(s1.score)# 90s1.age1# 也可以用运算后赋值print(s1.age)# 19六、实例方法结论实例方法是定义在类里的函数第一个参数永远是self通过对象.方法名()调用。6.1 定义和调用classStudent:def__init__(self,name,age,score):self.namename self.ageage self.scorescore# 实例方法自我介绍defintroduce(self):print(f大家好我叫{self.name}今年{self.age}岁成绩{self.score}分)# 创建对象并调用方法s1Student(小明,18,85)s1.introduce()# 大家好我叫小明今年18岁成绩85分实例方法和普通函数几乎一样区别只有两点定义在类的内部第一个参数是self调用时不用手动传6.2 方法中调用其他方法classStudent:def__init__(self,name,score):self.namename self.scorescoredefis_pass(self):returnself.score60defintroduce(self):status及格ifself.is_pass()else不及格print(f{self.name}成绩{self.score}分{status})sStudent(小明,85)s.introduce()# 小明 成绩85分及格在introduce()中通过self.is_pass()调用了同一个类的另一个方法。这是面向对象的常见写法——方法之间通过self互相协作。6.3 带参数的实例方法方法除了self还可以有额外参数classStudent:def__init__(self,name,score):self.namename self.scorescoredefadd_score(self,points):self.scorepointsprint(f{self.name}加了{points}分现在成绩{self.score}分)sStudent(小明,85)s.add_score(10)# 小明 加了10分现在成绩95分s.add_score(5)# 小明 加了5分现在成绩100分七、类属性与实例属性的区别结论类属性属于类本身所有对象共享实例属性属于每个对象各自独立。这是本章最容易混淆的知识点我们慢慢来。7.1 什么是类属性类属性直接写在类里不在任何方法里属于类本身classStudent:# 类属性写在方法外面school第一中学def__init__(self,name,score):# 实例属性写在 __init__ 里self.namename self.scorescore s1Student(小明,85)s2Student(小红,92)# 类属性通过类名访问print(Student.school)# 第一中学# 类属性也可以通过对象访问print(s1.school)# 第一中学print(s2.school)# 第一中学7.2 类属性 vs 实例属性对比项类属性实例属性定义位置类体中方法外面__init__方法中self.属性名归属属于类属于每个对象共享性所有对象共享同一份每个对象各自一份访问方式类名.属性或对象.属性对象.属性修改方式类名.属性 新值对象.属性 新值典型用途所有对象共用的常量/计数器每个对象独有的数据7.3 一个容易踩的坑classStudent:school第一中学def__init__(self,name):self.namename s1Student(小明)s2Student(小红)# 通过类名修改类属性 → 所有对象都变Student.school第二中学print(s1.school)# 第二中学print(s2.school)# 第二中学# 通过对象修改类属性 → 其实是给对象添加了实例属性s1.school第三中学print(s1.school)# 第三中学s1 的实例属性遮蔽了类属性print(s2.school)# 第二中学s2 仍读类属性print(Student.school)# 第二中学类属性本身没变⚠️ 通过对象修改类属性时Python 不会改类属性而是给这个对象创建一个同名的实例属性。这叫遮蔽。修改类属性一律用类名.属性 新值避免混淆。7.4 类属性的典型用途对象计数器classStudent:count0# 类属性统计创建了多少个学生def__init__(self,name):self.namename Student.count1# 每创建一个对象计数器 1print(f{self.name}入学当前学生总数{Student.count})s1Student(小明)# 小明 入学当前学生总数1s2Student(小红)# 小红 入学当前学生总数2s3Student(小刚)# 小刚 入学当前学生总数3print(f一共创建了{Student.count}个学生对象)# 一共创建了 3 个学生对象类属性count被所有对象共享每次__init__执行时Student.count 1就能统计总人数。这是类属性最常见的应用场景。八、Scratch 积木对照ScratchPython说明角色小猫对象实例Scratch 拖一个角色到舞台 Python 实例化一个对象角色属性x坐标/大小/造型实例属性self.xxx每个角色有自己的属性值 每个对象有自己的实例属性角色脚本积木堆实例方法def xxx(self)角色的脚本让角色做事 对象的方法让对象做事# Scratch 角色 → Python 对象# Scratch: 拖一只小猫到舞台设置 x100, y50脚本当绿旗点击 → 说你好# Python:classCat:def__init__(self,x,y):self.xx# 相当于角色的 x 坐标self.yy# 相当于角色的 y 坐标defsay_hello(self):# 相当于角色的说积木print(f小猫在({self.x},{self.y})说你好)catCat(100,50)# 创建小猫对象相当于拖角色到舞台cat.say_hello()# 小猫在(100, 50)说你好在 Scratch 里你先选一个角色给它设属性、写脚本然后把它拖到舞台上就有了一只活的角色。Python 面向对象也是这个流程先写class定义角色模板再实例化创建具体的角色每个角色有自己的属性和可以执行的动作。九、综合实战学生信息管理类综合运用类定义、__init__、self、实例方法、属性操作写一个学生信息管理类# # 学生信息管理类# classStudent:# 类属性学校名称所有学生共享school第一中学def__init__(self,name,age,score):初始化学生信息self.namename# 姓名self.ageage# 年龄self.scorescore# 成绩defintroduce(self):自我介绍print(f大家好我是{self.school}的{self.name}今年{self.age}岁成绩{self.score}分)defis_pass(self):判断是否及格60分及格ifself.score60:print(f{self.name}成绩{self.score}分及格了 ✅)returnTrueelse:print(f{self.name}成绩{self.score}分不及格 ❌)returnFalsedefadd_score(self,points):加分给成绩加上指定分数self.scorepointsprint(f{self.name}加了{points}分现在成绩{self.score}分)# 创建学生对象 print(*40)s1Student(小明,18,55)s2Student(小红,17,88)# 自我介绍s1.introduce()s2.introduce()print(-*40)# 判断及格s1.is_pass()s2.is_pass()print(-*40)# 小明补习加分再判断s1.add_score(15)# 加15分s1.is_pass()# 重新判断print(-*40)# 查看学校类属性print(f{s1.name}和{s2.name}都在{Student.school})运行结果 大家好我是第一中学的小明今年18岁成绩55分 大家好我是第一中学的小红今年17岁成绩88分 ---------------------------------------- 小明 成绩55分不及格 ❌ 小红 成绩88分及格了 ✅ ---------------------------------------- 小明 加了15分现在成绩70分 小明 成绩70分及格了 ✅ ---------------------------------------- 小明 和 小红 都在 第一中学分步拆解类属性school所有学生共享同一个学校名称通过self.school或Student.school访问__init__初始化创建对象时自动执行把传入的姓名、年龄、成绩存为实例属性introduce()方法通过self.name、self.age、self.score拼接自我介绍还访问了类属性self.schoolis_pass()方法判断成绩是否大于等于 60返回True/False同时打印结果add_score()方法修改实例属性self.score展示了方法可以改变对象状态方法间协作add_score()改了分数后再调is_pass()就能得到新结果——对象的状态是持续保存的十、常见报错速查表报错信息出现场景原因解决方法TypeError: __init__() missing N required positional argument实例化对象创建对象时少传了参数检查__init__需要几个参数不含 self实例化时全部传入AttributeError: Dog object has no attribute xxx访问属性对象没有这个属性或__init__中忘记定义在__init__中添加self.xxx 值TypeError: bark() takes 0 positional arguments but 1 was given调用方法定义方法时漏写了self参数方法第一个参数必须是selfNameError: name self is not defined类外部使用 self在类外面或类方法外用了selfself只能在类的方法内部使用TypeError: type object is not subscriptable实例化语法错误把Dog()写成了Dog[]实例化用小括号类名()十一、本章小结本章你正式迈入面向对象编程的大门类与对象——类是模板模具对象是按模板创建的具体实例用class定义类用类名()实例化对象__init__初始化——对象创建时自动执行通过self.属性 值设置初始属性self参数——就是当前对象自己方法内通过self访问属性和调用其他方法实例属性——每个对象各自拥有的数据在__init__中定义实例方法——定义在类里的函数第一个参数是self通过对象.方法名()调用类属性 vs 实例属性——类属性所有对象共享实例属性各自独立修改类属性用类名.属性 新值面向对象是 Python 编程的分水岭。别着急多写几遍类你会发现它就是把数据和操作数据的函数打包在一起逻辑更清晰。往期回顾《Python 零基础入门从积木到代码》专栏序零基础学 Python 第1章 | 全平台装环境 VS Code 配置 第一个 Hello World零基础学 Python 第2章 | print 输出 变量赋值 input 交互输入零基础学 Python 第3章 | 条件判断if / elif / else零基础学 Python 第 4 章 | for 循环与 range()让程序帮你重复干活零基础学 Python 第 5 章 | while 循环与循环嵌套让程序看着条件自己干活零基础学 Python 第 6 章 | 元组与集合不可变数据与自动去重零基础学 Python 第7章 | 字典 dict键值对存储零基础学 Python 第8章 | 字符串操作与格式化输出零基础学 Python 第9章 | 函数基础def、参数与返回值零基础学 Python 第10章 | 函数进阶参数灵活用法与作用域零基础学 Python 第11章 | 匿名函数与高阶函数零基础学 Python 第12章 | 文件读写让数据持久保存零基础学 Python 第13章 | 异常处理try-except 让程序不崩溃零基础学 Python 第14章 | 模块、包与第三方库下一章预告你已经会定义类和创建对象了但如果每次都要从头写一个全新的类太累了吧下一章学习继承与方法重写——让子类直接复用父类的属性和方法再按需修改代码复用效率翻倍。文末资源区资源说明Python 官方文档 - 类与对象https://docs.python.org/3/tutorial/classes.htmlPython 官方文档 - 类的定义https://docs.python.org/3/reference/datamodel.html#classes本章完整源码chapter15_all.py关注梅雅达编程笔记评论领资料|每节课都配套课后练习题与完整源码。代码报错、看不懂知识点可在评论区粘贴问题逐一解答欢迎关注梅雅达编程笔记持续分享Python零基础学习内容