Python教程
参考黑马程序员 Python 快速入门路线整理的零基础到综合案例笔记
11. 面向对象基础
11.1 什么是面向对象
面向对象是一种组织代码的方式。它把数据和操作数据的函数放在一起,形成对象。
面向过程:
name = "小明"
age = 18
def introduce(name, age):
print(f"我叫{name},今年{age}岁")
introduce(name, age)
面向对象:
class Student:
def introduce(self):
print(f"我叫{self.name},今年{self.age}岁")
student = Student()
student.name = "小明"
student.age = 18
student.introduce()
面向对象更适合数据结构和行为绑定在一起的场景,例如学生、用户、订单、商品、账户。
11.2 类和对象
类是模板,对象是根据模板创建出来的具体实例。
class Student:
pass
student1 = Student()
student2 = Student()
Student 是类,student1 和 student2 是对象。
11.3 属性
属性是对象保存的数据。
class Student:
pass
student = Student()
student.name = "小明"
student.age = 18
print(student.name)
print(student.age)
这种写法可以用,但实际项目中更推荐使用构造方法初始化属性。
11.4 方法
类中的函数叫方法。
class Student:
def introduce(self):
print(f"我叫{self.name},今年{self.age}岁")
student = Student()
student.name = "小明"
student.age = 18
student.introduce()
self 表示当前对象。调用方法时不需要手动传入 self,Python 会自动传。
11.5 构造方法__init__
__init__ 在对象创建时自动执行,用于初始化属性。
class Student:
def __init__(self, name, age, score):
self.name = name
self.age = age
self.score = score
def introduce(self):
print(f"我叫{self.name},今年{self.age}岁,成绩{self.score}")
student = Student("小明", 18, 95)
student.introduce()
构造方法的好处:
- 创建对象时必须提供必要数据。
- 属性初始化集中,不容易漏。
- 对象状态更完整。
11.6 str
直接打印对象时,默认输出不直观。可以定义 __str__。
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"Student(name={self.name}, age={self.age})"
student = Student("小明", 18)
print(student)
11.7 封装
封装就是把数据和方法放到类中,并控制访问方式。
Python 中以双下划线开头的属性通常视为私有属性。
class Account:
def __init__(self, owner, balance):
self.owner = owner
self.__balance = balance
def get_balance(self):
return self.__balance
def deposit(self, money):
if money <= 0:
print("存款金额必须大于0")
return
self.__balance += money
def withdraw(self, money):
if money <= 0:
print("取款金额必须大于0")
return
if money > self.__balance:
print("余额不足")
return
self.__balance -= money
account = Account("小明", 1000)
account.deposit(200)
account.withdraw(100)
print(account.get_balance())
封装的意义是避免外部随意修改内部状态。
11.8 继承
继承可以让子类复用父类的属性和方法。
class Animal:
def eat(self):
print("吃东西")
class Dog(Animal):
def bark(self):
print("汪汪")
dog = Dog()
dog.eat()
dog.bark()
子类可以扩展新方法,也可以重写父类方法。
11.9 方法重写
class Animal:
def speak(self):
print("动物叫")
class Dog(Animal):
def speak(self):
print("汪汪")
class Cat(Animal):
def speak(self):
print("喵喵")
dog = Dog()
cat = Cat()
dog.speak()
cat.speak()
11.10 super
子类可以通过 super() 调用父类方法。
class Person:
def __init__(self, name):
self.name = name
class Student(Person):
def __init__(self, name, score):
super().__init__(name)
self.score = score
student = Student("小明", 95)
print(student.name, student.score)
11.11 多态
多态指不同对象响应同一个方法,表现出不同结果。
class Dog:
def speak(self):
print("汪汪")
class Cat:
def speak(self):
print("喵喵")
def make_sound(animal):
animal.speak()
make_sound(Dog())
make_sound(Cat())
Python 更关注对象是否有需要的方法,而不是对象具体是什么类。
11.12 类属性和实例属性
实例属性属于对象:
class Student:
def __init__(self, name):
self.name = name
类属性属于类,所有对象共享:
class Student:
school = "黑马学校"
def __init__(self, name):
self.name = name
s1 = Student("小明")
s2 = Student("小红")
print(s1.school)
print(s2.school)
print(Student.school)
如果每个对象都不同,用实例属性。如果所有对象共享,用类属性。
11.13 类方法和静态方法
11.13.1 类方法
类方法使用 @classmethod,第一个参数通常是 cls。
class Student:
school = "黑马学校"
@classmethod
def get_school(cls):
return cls.school
print(Student.get_school())
11.13.2 静态方法
静态方法使用 @staticmethod,不需要访问实例和类。
class MathUtils:
@staticmethod
def add(a, b):
return a + b
print(MathUtils.add(1, 2))
静态方法本质上是放在类命名空间里的普通函数。
11.14 dataclass
dataclass 可以快速定义主要用于保存数据的类。
from dataclasses import dataclass
@dataclass
class Student:
name: str
age: int
score: float
student = Student("小明", 18, 95)
print(student)
它会自动生成 __init__、__repr__ 等方法。适合数据模型类。
11.15 小案例:学生类
class Student:
def __init__(self, student_id, name, age, score):
self.student_id = student_id
self.name = name
self.age = age
self.score = score
def is_passed(self):
return self.score >= 60
def to_dict(self):
return {
"student_id": self.student_id,
"name": self.name,
"age": self.age,
"score": self.score,
}
@classmethod
def from_dict(cls, data):
return cls(
data["student_id"],
data["name"],
data["age"],
data["score"],
)
def __str__(self):
return f"{self.student_id} {self.name} {self.age} {self.score}"
student = Student("001", "小明", 18, 95)
print(student.is_passed())
print(student.to_dict())
to_dict() 和 from_dict() 适合对象与 JSON 数据之间转换。
11.16 易错点
- 类名推荐使用大驼峰,如
StudentManager。 - 方法第一个参数必须写
self,调用时不用传。 __init__不是普通方法,它在创建对象时自动执行。- 私有属性不是绝对安全,只是约定和名称改写。
- 不要为了面向对象而面向对象,简单脚本用函数就够。
- 类中方法太多时,说明职责可能过重。
11.17 本章练习
- 定义
Student类,包含姓名、年龄、成绩和自我介绍方法。 - 定义
Account类,实现存款、取款、查询余额。 - 定义
Circle类,计算圆的周长和面积。 - 定义
Dog、Cat类,并用同一个函数调用它们的speak()方法。 - 使用
dataclass定义一个商品类Product。