物件导向初步
进阶类别是图则、物件是实物。__init__ 设定初始属性,self 代表物件自己;属性存资料(s1.name),方法做行为(s1.introduce())。类别把资料和行为绑在一起,代码有条理易重用。
- 类别是图则,物件是按图则建成的实例;一个类别可建无限多个物件。
- 属性存资料(s1.name),方法做行为(s1.introduce())。
- __init__ 建构子在建立物件时自动执行,设定初始属性。
文体小知识:编程教学课每个概念都配一段可以亲手试的代码例子,照住输入、改一改,最快学会。
§课文原文 Passage
1物件导向编程(OOP,Object-Oriented Programming)把资料和行为包在一起管理。类别(Class)是图则:它定义「学生」有哪些资料和能做什么;物件(Object)是按图则建成的实物:小明、Mary 各是一个 Student 物件。一个类别可以建立无限多个物件。
2每个物件有属性(Attribute)— 它的资料,例如姓名、班别;也有方法(Method)— 它会做的事,例如自我介绍、计平均分。建立物件时 Python 会自动执行 __init__(建构子),把初始属性设定好;方法里的 self 代表「这个物件自己」,让每个物件存取自己的资料。
3定义一个学生类别:class Student: 之下 def __init__(self, name, cls): self.name = name, self.cls = cls。建立物件:s1 = Student("小明", "3A"),之后 s1.name 得 "小明"。加方法:def introduce(self): print("我是" + self.name + ",读" + self.cls),呼叫 s1.introduce() 就印出「我是小明,读3A」。
4为什么要用 OOP?一个班几十个学生,每个都有姓名、成绩、行为 — 用清单和散乱变数很快就混乱;用类别把「学生的资料」和「学生能做的事」绑在一起,代码有条理、容易重用。游戏角色、手机 App、学校系统背后几乎都是这样组织的。
1重点摘要 Summary
类别是图则、物件是实物。__init__ 设定初始属性,self 代表物件自己;属性存资料(s1.name),方法做行为(s1.introduce())。类别把资料和行为绑在一起,代码有条理易重用。
2生字卡 Vocabulary
定义一类物件的资料与行为的图则,例如 Student 类别。
按类别建立的实例,拥有自己的属性,例如小明的 Student 物件。
物件内储存的资料,例如 s1.name、s1.cls。
物件可以执行的函数,定义在类别内,例如 introduce()。
建立物件时自动执行的特殊方法,用来设定初始属性。
方法中的第一个参数,代表呼叫该方法的物件本身,借此存取自己的属性。
物件的同义词:由类别实际产生出来的一份个体。
由类别建立物件的动作,例如 s1 = Student("小明", "3A")。
把资料和操作资料的方法包在同一类别内,外界不必理会内部细节。
3逐步讲解 Steps
- 类别与物件的概念物件导向编程(OOP)把资料与行为包装在一起管理。类别(Class)是图则,定义「学生」这类事物有哪些资料、能做什么;物件(Object)是按图则建成的实物,小明与 Mary 各是一个 Student 物件。一个类别可以建立无数个物件,如同一份图则可以兴建无数个单位。现实对照:手机 App 中的每则讯息、每个联络人、每件商品,背后都是某个类别的物件。
- 用 __init__ 设定属性属性(Attribute)是物件携带的资料。在类别内定义 __init__ 方法(建构子),建立物件时 Python 会自动执行它:def __init__(self, name, cls): self.name = name 与 self.cls = cls 两行,把传入的 "小明" 与 "3A" 存进该物件。self 代表「这个物件自己」,令每个物件各自保管自己的资料。参数名称可以任意,但 self 必须排在第一位,这是 Python 的固定规则。
- 建立物件与读取属性以 Student("小明", "3A") 建立物件并存入变数 s1。之后用点号存取属性:s1.name 得 "小明",s1.cls 得 "3A"。属性可以随时修改:s1.cls = "3C" 之后再读 s1.cls 便得 "3C"。多个物件互不干扰:s2 = Student("Mary", "3B") 之后,修改 s1 的属性完全不影响 s2,因为每个物件有自己独立的属性副本,如同两个学生各自持有自己的学生证。
- 方法:物件能做的事方法(Method)是类别内定义的函式,代表物件能做的事。def introduce(self): print("我是" + self.name + ",读" + self.cls) 定义之后,呼叫 s1.introduce() 印出「我是小明,读3A」。文法要点:定义时参数必须有 self,呼叫时则完全不传,Python 会自动把 s1 填入 self。方法内可以读取 self 的任何属性,因此每次呼叫都用的是最新资料,不会过时。
- 方法用属性做计算方法不只显示资料,还能做计算。在类别内加入 def average(self): return sum(self.marks) / len(self.marks),并令 s1.marks = [80, 90, 70],呼叫 s1.average() 得 80.0。资料与计算绑在同一物件内:成绩属性更新之后,average 自动反映新数据,不必另行维护。这正是 OOP 的核心优势——「谁的资料,谁的行为」,学生物件管好自己的成绩与计算,程式结构便清晰分明。
- 为什么要用物件导向设想处理全班几十个学生:每人有姓名、班别、成绩清单,还要计平均分、列自我介绍。用散乱的清单与变数,很快便会出现 names[3] 与 marks[3] 对不上位的混乱;用类别把「学生的资料」与「学生能做的事」绑在一起,每个学生一个物件,程式立即有条理。改动 average 方法一行,所有学生物件同步更新。游戏角色、学校系统、购物平台,几乎都以 OOP 组织程式。
- 完整例子与常见错误完整定义:class Student: 之下先写 __init__ 存姓名与成绩,再写 average 方法。建立 s = Student("Mary", [80, 90, 70]),呼叫 print(s.average()) 得 80.0。常见错误有三:定义方法时忘记 self,程式报错;呼叫时画蛇添足写成 s1.introduce(s1),Python 会把 s1 当成第二个参数;__init__ 拼写错误(前后各两条底线),属性便不会自动设定。逐项避开,类别便可顺利运作。
4图解 Diagrams
5例题示范 Example
例题:定义 Student 类别(姓名与成绩清单属性),加入 average() 方法,并为成绩 [80, 90, 70] 的 Mary 计算平均分。
- 定义类别与建构子:class Student: 之内 def __init__(self, name, marks): self.name = name,下一行 self.marks = marks。
- 加入计算方法:def average(self): return sum(self.marks) / len(self.marks),直接使用物件自己的 marks 属性。
- 建立物件:s = Student("Mary", [80, 90, 70]),建构子自动把两项资料存好。
- 呼叫方法:print(s.average());sum([80, 90, 70]) = 240,240 ÷ 3 = 80.0。
- 延伸:再建第二个物件 Student("Peter", [60, 65]),呼叫其 average() 得 62.5,两个物件互不干扰。
- 答案:s.average() 回传 80.0,即 Mary 三科的平均分。类别把资料(marks)与计算(average)绑在一起,每个物件各自保管成绩,方法自动使用该物件的最新数据。
6常见错误 Mistakes
75 题快测 Quick check
Q1类别和物件的关系,哪个说法正确?A. 类别是图则,物件是按图则建成的实例 B. 物件是图则,类别是实例 C. 两者完全相同
Q2建立物件时,哪个方法会自动执行?
Q3s1 = Student("小明", "3A") 之后,s1.name 的值是什么?
Q4方法定义 def introduce(self): 中,self 的作用是什么?
Q5s1.marks = [70, 80],方法 average() 回传 sum(self.marks) / len(self.marks)。s1.average() 是多少?
8重点回顾 Recap
- 类别是图则,物件是按图则建成的实例;一个类别可建无限多个物件。
- 属性存资料(s1.name),方法做行为(s1.introduce())。
- __init__ 建构子在建立物件时自动执行,设定初始属性。
- self 代表物件自己;方法定义要有 self,呼叫时不用传。
- 每个物件的属性各自独立;OOP 把资料和行为绑在一起,代码有条理易重用。