第25课:面向对象编程:类与对象
1. 学习目标
通过本节课的学习,你将能够:
- 理解面向对象编程(OOP)中"类"和"对象"的核心概念及其关系。
- 掌握如何定义一个简单的类,并使用它来创建对象。
- 理解并区分对象的"属性"和"方法"。
- 掌握
self参数在类的方法中的基本作用。 - 能够为对象动态地添加和修改属性。
2. 核心概念
类(Class) 可以理解为一张"图纸"或"蓝图"。它描述了一类事物共有的特征(属性)和行为(方法)。例如,"汽车"这个类定义了所有汽车都应该有颜色、品牌等特征,以及启动、行驶等行为。
对象(Object) 是根据"类"这张图纸制造出来的具体"产品"或"实例"。每一辆根据"汽车"图纸制造出来的具体车(如"我的那辆红色特斯拉"),都是一个对象。对象拥有类中定义的属性和方法。
简而言之:类是模板,对象是实例。
属性(Attribute) 是描述对象状态的数据,通常以变量的形式存在。例如,汽车的颜色、品牌、当前速度。
方法(Method) 是描述对象可以执行的操作,通常以函数的形式存在。例如,汽车的启动()、加速()、刹车()。
3. 代码示例
# 定义一个名为 `Dog` 的类
class Dog:
# 这是一个类属性,所有 `Dog` 类的对象共享这个属性
species = "Canis familiaris"
# 定义一个方法:所有狗都会"汪汪叫"
# 注意:每个方法的第一个参数都是 `self`,它代表调用这个方法的对象实例本身
def bark(self):
return "汪汪!"
# 现在,我们根据 `Dog` 类这个蓝图,来创建两个具体的"对象"(实例)
my_dog = Dog()
your_dog = Dog()
# 为 `my_dog` 这个对象添加实例属性(每个对象独有的属性)
my_dog.name = "旺财"
my_dog.age = 3
# 为 `your_dog` 这个对象添加实例属性
your_dog.name = "来福"
your_dog.age = 2
# 访问对象的属性
print(f"我的狗叫 {my_dog.name},它{my_dog.age}岁了。")
print(f"你的狗叫 {your_dog.name},它{your_dog.age}岁了。")
# 访问类属性(通过类名或任意一个对象访问)
print(f"所有狗的物种都是:{Dog.species}")
print(f"我的狗的物种也是:{my_dog.species}")
# 调用对象的方法
print(f"{my_dog.name} 说:{my_dog.bark()}")
print(f"{your_dog.name} 说:{your_dog.bark()}")
运行结果:
我的狗叫 旺财,它3岁了。
你的狗叫 来福,它2岁了。
所有狗的物种都是:Canis familiaris
我的狗的物种也是:Canis familiaris
旺财 说:汪汪!
来福 说:汪汪!
self 参数解释:
在 bark(self) 方法中,self 是一个约定俗成的参数名,它指向调用该方法的对象实例。当你调用 my_dog.bark() 时,Python 解释器会自动将 my_dog 对象作为第一个参数传递给 bark 方法,这就是 self。通过 self,方法内部可以访问该对象自己的属性和其他方法。
4. 实践练习
练习1:创建你的第一个类
- 定义一个名为
Car的类。 - 给这个类添加一个类属性
wheels,值为4。 - 创建一个
Car类的对象my_car。 - 为
my_car对象添加实例属性brand(例如 "Toyota") 和color(例如 "Blue")。 - 打印出
my_car的brand、color和wheels属性。 - 预期输出示例:
我的车是蓝色的丰田,它有4个轮子。
练习2:添加方法
- 在练习1的
Car类中,添加一个方法describe()。 - 这个方法应该使用
self参数来访问对象的brand和color属性,并返回一个描述字符串,例如 "这是一辆蓝色的丰田。"。 - 创建一个新对象
your_car,并为其设置属性。 - 分别调用
my_car和your_car的describe()方法并打印结果。
练习3:动态修改属性
- 接续练习2,将
my_car的color属性从 "Blue" 修改为 "Red"。 - 再次调用
my_car.describe()方法,观察输出的变化。 - 预期输出示例:
这是一辆蓝色的丰田。 这是一辆白色的本田。 这是一辆红色的丰田。 # 颜色已改变
5. 常见错误
-
忘记
self参数:在定义类的方法时,忘记在参数列表中加上self。这会导致在调用方法时出现TypeError: 方法名() takes 0 positional arguments but 1 was given错误,因为 Python 会自动传入实例作为第一个参数。# 错误示例 class MyClass: def say_hello(): # 缺少 self print("Hello") obj = MyClass() obj.say_hello() # 报错 -
混淆类属性和实例属性:试图通过对象去修改一个类属性,这通常不会修改类本身,而是会为这个对象创建一个同名的实例属性,从而"遮蔽"了类属性。
class Dog: species = "Canis familiaris" dog1 = Dog() dog1.species = "Wolf" # 这为dog1创建了一个新的实例属性 `species` print(dog1.species) # 输出: Wolf (访问的是实例属性) print(Dog.species) # 输出: Canis familiaris (类属性未改变) dog2 = Dog() print(dog2.species) # 输出: Canis familiaris (dog2没有实例属性,所以访问类属性) -
误用类名调用实例方法:实例方法必须通过对象来调用,不能直接用类名调用,除非该方法被明确声明为静态方法或类方法(后续课程会讲)。
class MyClass: def instance_method(self): return "I am an instance method." # MyClass.instance_method() # 错误!缺少实例参数 obj = MyClass() obj.instance_method() # 正确
6. 小结
- 类是创建对象的模板,定义了对象应有的属性和行为。
- 对象是类的实例,是具体存在的实体。
- 属性用于存储对象的状态数据,分为所有实例共享的类属性和每个实例独有的实例属性。
- 方法定义了对象可以执行的操作,本质上是定义在类中的函数。
self是类的方法中必备的第一个参数,它代表方法被调用时的实例对象本身,通过它才能访问该对象的属性和其它方法。- 对象的属性可以在创建后动态地添加或修改。
理解了类和对象的基本概念,我们就能以一种更结构化、更贴近现实世界建模的方式来组织代码。下一课,我们将学习一个特殊的方法 __init__,它能让我们在创建对象时,就自动地为其属性进行初始化,使代码更加整洁和强大。