完整讲解 · 5 段教学·配 4 道练习题·预计 35 分钟
本页是本章的通读版,可直接读完全部讲解。想动手写代码、跑判分,去 闯关模式。
编程语言中,一般有两种编程思维:面向过程和面向对象。
Python 是一门面向对象的语言。如果你听过 Java 的「万事万物皆对象」,Python 也是这样。
| 概念 | 含义 |
|---|---|
| 类(class) | 一类事物的「模板」——定义这类事物有哪些属性、能做哪些事 |
| 对象(object) | 由类创建出来的「实例」 |
举个例子,Dog 是一个类(描述「狗」这种东西的属性和行为),小白 是一只具体的狗(Dog 类的一个对象)。
| 特性 | 简单说 |
|---|---|
| 封装 | 把数据和操作打包到一起 |
| 继承 | 子类自动获得父类的属性和方法 |
| 多态 | 同一个方法,不同的类可以有不同的行为 |
如果你是初次接触面向对象,看到这里还有点蒙也没关系——下面通过例子逐步理解。
类是什么?最直观的理解:类是变量和函数的集合。
┌─────────────────┐
│ 类 │
│ ┌───────────┐ │
│ │ 属性 1 │ │ ← 数据(变量)
│ │ 属性 2 │ │
│ └───────────┘ │
│ + │
│ ┌───────────┐ │
│ │ 方法 1 │ │ ← 行为(函数)
│ │ 方法 2 │ │
│ └───────────┘ │
└─────────────────┘
我们把「同一性质」的数据和行为打包到一起,方便重复使用。
class 类名:
# 属性 + 方法
pass例子——定义一个 Person 类:
class Person:
species = '人类' # 类属性
def greet(self): # 方法
print('你好')💡 关于
self:方法的第一个参数永远是self,代表「当前正在调用这个方法的对象」。调用时不用自己传,Python 会自动传进去。
class Person:
species = '人类'
def greet(self):
print('你好')
# 实例化(创建一个 Person 对象)
p = Person()
# 通过对象访问属性
print(p.species)
# 通过对象调用方法
p.greet()输出:
人类
你好
__init__上一节我们的 Person 没有名字、没有年龄——所有 Person 都长得一模一样。
实际中我们希望每个对象都带自己的属性——比如「张三 18 岁」、「李四 25 岁」。这时候要用初始化函数 __init__。
__init____init__ 在你创建对象时自动被调用——专门用来初始化新对象的属性。
写法:
class 类名:
def __init__(self, 参数1, 参数2, ...):
self.属性1 = 参数1
self.属性2 = 参数2注意:
__init__ 前后各两个下划线——不是一个selfself 上设置的属性就是这个对象专属的(不同对象互不影响)class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
print(f'我叫 {self.name},今年 {self.age} 岁')
# 实例化时传入参数
p1 = Person('张三', 18)
p2 = Person('李四', 25)
p1.greet()
p2.greet()输出:
我叫 张三,今年 18 岁
我叫 李四,今年 25 岁
每个对象都有自己的 name 和 age——互不干扰。这就是 OOP 的「封装」效果。
「继承」就是子类自动获得父类的所有属性和方法——可以再加自己的,也可以「重写」父类的。
class 子类(父类):
...例子——Student 继承 Person:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
print(f'我叫 {self.name},今年 {self.age} 岁')
class Student(Person):
pass # 啥都不加,但已经继承了 __init__ 和 greet
s = Student('小明', 16)
s.greet()输出:
我叫 小明,今年 16 岁
Student 没写任何代码,但自动具备 Person 的初始化和 greet 方法。这就是继承的好处。
class Student(Person):
def __init__(self, name, age, school):
super().__init__(name, age) # 调父类的 __init__
self.school = school
def study(self):
print(f'{self.name} 正在 {self.school} 学习')
s = Student('小明', 16, '希望小学')
s.greet()
s.study()输出:
我叫 小明,今年 16 岁
小明 正在 希望小学 学习
super() 是「父类」的引用,用来调用父类的方法——避免把同样的代码再写一遍。
多态的概念其实不难理解:对不同类型的对象做相同的操作,会根据类型的不同表现出不同的行为。
简单说就是「重写父类的方法」——子类的同名方法盖掉父类的。
class Animal:
def sound(self):
print('一些声音')
class Dog(Animal):
def sound(self):
print('汪汪')
class Cat(Animal):
def sound(self):
print('喵喵')
# 注意:调用方都是 .sound(),但是行为完全不同
animals = [Dog(), Cat(), Animal()]
for a in animals:
a.sound()输出:
汪汪
喵喵
一些声音
调用 .sound() 时,实际执行的是哪段代码取决于对象的真实类型。这就是多态——同一个方法名,不同的类有不同的实现。
最大的好处是写代码的人不用关心具体类型:
def make_sound(animal):
animal.sound()
make_sound(Dog()) # 汪汪
make_sound(Cat()) # 喵喵make_sound 只要求传进来的对象有 .sound() 方法就行——不管它是 Dog 还是 Cat 还是别的。这让代码更容易扩展。
读完了?动手练一遍才算真会。
去闯关模式练习 →