Cherish's Notebook
切换到深色模式
菜单
Wiki--浏览次数--访问次数--跳出率--平均停留

Python教程

参考黑马程序员 Python 快速入门路线整理的零基础到综合案例笔记

11. 面向对象基础

11.1 什么是面向对象

面向对象是一种组织代码的方式。它把数据和操作数据的函数放在一起,形成对象。

面向过程:

CODE
name = "小明"
age = 18

def introduce(name, age):
    print(f"我叫{name},今年{age}岁")

introduce(name, age)

面向对象:

CODE
class Student:
    def introduce(self):
        print(f"我叫{self.name},今年{self.age}岁")


student = Student()
student.name = "小明"
student.age = 18
student.introduce()

面向对象更适合数据结构和行为绑定在一起的场景,例如学生、用户、订单、商品、账户。

11.2 类和对象

类是模板,对象是根据模板创建出来的具体实例。

CODE
class Student:
    pass


student1 = Student()
student2 = Student()

Student 是类,student1student2 是对象。

11.3 属性

属性是对象保存的数据。

CODE
class Student:
    pass


student = Student()
student.name = "小明"
student.age = 18

print(student.name)
print(student.age)

这种写法可以用,但实际项目中更推荐使用构造方法初始化属性。

11.4 方法

类中的函数叫方法。

CODE
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__ 在对象创建时自动执行,用于初始化属性。

CODE
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()

构造方法的好处:

  1. 创建对象时必须提供必要数据。
  2. 属性初始化集中,不容易漏。
  3. 对象状态更完整。

11.6 str

直接打印对象时,默认输出不直观。可以定义 __str__

CODE
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 中以双下划线开头的属性通常视为私有属性。

CODE
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 继承

继承可以让子类复用父类的属性和方法。

CODE
class Animal:
    def eat(self):
        print("吃东西")


class Dog(Animal):
    def bark(self):
        print("汪汪")


dog = Dog()
dog.eat()
dog.bark()

子类可以扩展新方法,也可以重写父类方法。

11.9 方法重写

CODE
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() 调用父类方法。

CODE
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 多态

多态指不同对象响应同一个方法,表现出不同结果。

CODE
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 类属性和实例属性

实例属性属于对象:

CODE
class Student:
    def __init__(self, name):
        self.name = name

类属性属于类,所有对象共享:

CODE
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

CODE
class Student:
    school = "黑马学校"

    @classmethod
    def get_school(cls):
        return cls.school


print(Student.get_school())

11.13.2 静态方法

静态方法使用 @staticmethod,不需要访问实例和类。

CODE
class MathUtils:
    @staticmethod
    def add(a, b):
        return a + b


print(MathUtils.add(1, 2))

静态方法本质上是放在类命名空间里的普通函数。

11.14 dataclass

dataclass 可以快速定义主要用于保存数据的类。

CODE
from dataclasses import dataclass


@dataclass
class Student:
    name: str
    age: int
    score: float


student = Student("小明", 18, 95)
print(student)

它会自动生成 __init____repr__ 等方法。适合数据模型类。

11.15 小案例:学生类

CODE
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 易错点

  1. 类名推荐使用大驼峰,如 StudentManager
  2. 方法第一个参数必须写 self,调用时不用传。
  3. __init__ 不是普通方法,它在创建对象时自动执行。
  4. 私有属性不是绝对安全,只是约定和名称改写。
  5. 不要为了面向对象而面向对象,简单脚本用函数就够。
  6. 类中方法太多时,说明职责可能过重。

11.17 本章练习

  1. 定义 Student 类,包含姓名、年龄、成绩和自我介绍方法。
  2. 定义 Account 类,实现存款、取款、查询余额。
  3. 定义 Circle 类,计算圆的周长和面积。
  4. 定义 DogCat 类,并用同一个函数调用它们的 speak() 方法。
  5. 使用 dataclass 定义一个商品类 Product