第 9 章 类


提示:

1.第 9 章 类

9.1 创建和使用类

类是面向对象编程的核心,它是一种“模板”,用于定义对象的属性(特征)和方法(行为)。通过类可以创建多个具有相同结构的对象(实例)。

9.1.1 创建 Dog 类

以“狗”为例,一个简单的Dog类可以包含狗的属性(如名字、年龄)和方法(如坐、叫)。
示例代码

class Dog:
    """一次模拟小狗的简单尝试"""
    def __init__(self, name, age):  # 初始化方法,创建实例时自动调用
        """初始化属性name和age"""
        self.name = name  # self.name是实例属性,将参数name的值赋给它
        self.age = age    # self.age同理

    def sit(self):  # 方法:模拟小狗坐下
        """模拟小狗收到命令时坐下"""
        print(f"{self.name} is now sitting.")

    def roll_over(self):  # 方法:模拟小狗打滚
        """模拟小狗收到命令时打滚"""
        print(f"{self.name} rolled over!")
# 测试代码
my_dog = Dog("小白", 2)
my_dog.sit()
my_dog.roll_over()
  • __init__()方法:是类的特殊方法(构造方法),当创建实例时自动执行,用于初始化对象的属性。self是必需的参数,代表实例本身,通过self可以访问实例的属性和方法。
  • 类中的函数称为“方法”,与普通函数的区别是:方法的第一个参数必须是self
9.1.2 根据类创建实例

创建实例(对象)就是用类作为模板生成具体的个体。通过实例可以访问属性和调用方法。
示例代码

class Dog:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def sit(self):
        print(f"{self.name}")
    def roll_over(self):
        print(f"{self.name} rolled over!")
# 创建Dog类的实例(对象)
my_dog = Dog("Willie", 6)  # 传入name和age参数,self无需手动传值

# 访问实例的属性(格式:实例名.属性名)
print(f"My dog's name is {my_dog.name}.")  # 输出:My dog's name is Willie.
print(f"My dog is {my_dog.age} years old.")  # 输出:My dog is 6 years old.

# 调用实例的方法(格式:实例名.方法名())
my_dog.sit()  # 输出:Willie is now sitting.
my_dog.roll_over()  # 输出:Willie rolled over!
  • 可以创建多个实例,每个实例的属性独立:
    your_dog = Dog("Lucy", 3)
    your_dog.sit()  # 输出:Lucy is now sitting.
    

9.2 使用类和实例

通过类创建实例后,通常需要修改实例的属性、设置默认属性等,以灵活满足需求。

9.2.1 Car 类

以“汽车”为例,Car类可以包含更多属性(如制造商、型号、年份)和方法(如描述汽车、更新里程)。
示例代码

class Car:
    """一次模拟汽车的简单尝试"""
    def __init__(self, make, model, year):
        """初始化汽车的属性"""
        self.make = make    # 制造商
        self.model = model  # 型号
        self.year = year    # 年份

    def get_descriptive_name(self):  # 返回汽车的详细描述
        """返回整洁的描述性信息"""
        long_name = f"{self.year} {self.make} {self.model}"
        return long_name.title()

my_new_car = Car("audi", "a4", 2024)
print(my_new_car.get_descriptive_name())  # 输出:2024 Audi A4
9.2.2 给属性指定默认值

__init__()方法中,可以为属性设置默认值,这样创建实例时就无需手动传入该参数。
示例:给汽车添加“里程数”属性,并设置默认值为0:

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0  # 默认值:里程数初始为0

    def read_odometer(self):  # 读取里程数
        print(f"This car has {self.odometer_reading} miles on it.")

my_new_car = Car("audi", "a4", 2024)
my_new_car.read_odometer()  # 输出:This car has 0 miles on it.
9.2.3 修改属性的值

修改属性值的方式有三种:

  1. 直接通过实例修改:最简单的方式,直接给实例的属性赋值。

    my_new_car.odometer_reading = 23  # 直接修改里程数
    my_new_car.read_odometer()  # 输出:This car has 23 miles on it.
    
  2. 通过方法修改:在类中定义方法,通过调用方法修改属性(可添加逻辑验证,如防止里程数减少)。

    class Car:
        # ... 其他代码省略 ...
        def update_odometer(self, mileage):
            """将里程表读数设置为指定值,禁止回调里程数"""
            if mileage >= self.odometer_reading:  # 确保里程数不减少
                self.odometer_reading = mileage
            else:
                print("You can't roll back an odometer!")
    
    my_new_car.update_odometer(100)  # 调用方法修改
    my_new_car.read_odometer()  # 输出:This car has 100 miles on it.
    my_new_car.update_odometer(50)  # 尝试减少里程数,输出提示
    
  3. 通过方法递增:定义方法实现属性的递增(如累加里程)。

    class Car:
        # ... 其他代码省略 ...
        def increment_odometer(self, miles):
            """将里程表读数增加指定的量"""
            self.odometer_reading += miles
    
    my_new_car.increment_odometer(50)  # 增加50英里
    my_new_car.read_odometer()  # 输出:This car has 150 miles on it.
    

9.3 继承

继承是面向对象编程的重要特性,它允许一个类(子类)继承另一个类(父类)的属性和方法,同时可以添加自己的属性和方法,或重写父类的方法,实现代码复用和扩展。

9.3.1 子类的__init__()方法

创建子类时,需要在子类的__init__()方法中先调用父类的__init__()方法,以继承父类的属性。
示例:定义ElectricCar(电动车)类,继承Car类:

class ElectricCar(Car):  # 括号中为父类名,表示继承Car
    """电动汽车的独特之处"""
    def __init__(self, make, model, year):
        """初始化父类的属性"""
        super().__init__(make, model, year)  # super()函数调用父类的__init__()
        # 子类可以添加自己的属性(如电池容量)
        self.battery_size = 75

# 创建电动车实例
my_tesla = ElectricCar("tesla", "model s", 2024)
print(my_tesla.get_descriptive_name())  # 继承父类的方法,输出:2024 Tesla Model S
print(f"Battery size: {my_tesla.battery_size} kWh")  # 访问子类的属性
9.3.2 给子类定义属性和方法

子类可以拥有父类没有的属性和方法,以体现其独特性。
示例:给ElectricCar添加电池相关的方法:

class ElectricCar(Car):
    def __init__(self, make, model, year):
        super().__init__(make, model, year)
        self.battery_size = 75

    def describe_battery(self):  # 子类独有的方法
        """打印一条描述电池容量的消息"""
        print(f"This car has a {self.battery_size}-kWh battery.")

my_tesla = ElectricCar("tesla", "model s", 2024)
my_tesla.describe_battery()  # 输出:This car has a 75-kWh battery.
9.3.3 重写父类中的方法

如果父类的方法不符合子类的需求,可以在子类中重写该方法(方法名与父类完全相同)。
示例:父类Carfill_gas_tank()(加油)方法,电动车不需要加油,因此重写:

class Car:
    # ... 其他代码省略 ...
    def fill_gas_tank(self):
        """给汽车加油"""
        print("This car needs a gas tank!")

class ElectricCar(Car):
    # ... 其他代码省略 ...
    def fill_gas_tank(self):  # 重写父类方法
        """电动汽车没有油箱"""
        print("This car doesn't need a gas tank!")

my_tesla = ElectricCar("tesla", "model s", 2024)
my_tesla.fill_gas_tank()  # 调用子类重写的方法,输出:This car doesn't need a gas tank!
9.3.4 将实例用作属性

当类的属性或方法过于复杂时,可以将一部分功能拆分成另一个类,然后在原类中创建该类的实例作为属性,使代码更简洁。
示例:将电动车的电池功能拆分为Battery类,在ElectricCar中创建Battery实例:

class Battery:  # 电池类
    """一次模拟电动汽车电池的尝试"""
    def __init__(self, battery_size=75):  # 默认容量75kWh
        self.battery_size = battery_size

    def describe_battery(self):
        """描述电池容量"""
        print(f"This car has a {self.battery_size}-kWh battery.")

    def get_range(self):
        """打印电池的续航里程"""
        if self.battery_size == 75:
            range = 260
        elif self.battery_size == 100:
            range = 315
        print(f"This car can go about {range} miles on a full charge.")

class ElectricCar(Car):
    """电动汽车的独特之处"""
    def __init__(self, make, model, year):
        super().__init__(make, model, year)
        self.battery = Battery()  # 将Battery实例作为属性

my_tesla = ElectricCar("tesla", "model s", 2024)
my_tesla.battery.describe_battery()  # 调用属性的方法,输出:This car has a 75-kWh battery.
my_tesla.battery.get_range()  # 输出:This car can go about 260 miles on a full charge.
9.3.5 模拟实物

通过类、继承、属性拆分等功能,可以更真实地模拟现实中的复杂实物。例如:模拟一辆电动车时,不仅可以包含电池,还可以包含电机、充电系统等,每个部分都可以用独立的类实现,再组合到ElectricCar中。

9.4 导入类

当代码量较大时,将类存储在独立的模块(.py文件)中,再通过“导入”在主程序中使用,可以使代码结构更清晰。

9.4.1 导入单个类

将类定义在一个模块中(如car.py),然后在主程序中导入该类。
示例

  • car.py(模块文件):
    class Car:
        """汽车类的定义"""
        # ... 类的代码省略 ...
    
  • 主程序文件(如my_car.py):
    from car import Car  # 从car模块导入Car类
    
    my_car = Car("audi", "a4", 2024)
    print(my_car.get_descriptive_name())  # 正常使用Car类
    
9.4.2 在一个模块中存储多个类

一个模块可以包含多个相关的类,方便管理。
示例car.py中包含CarElectricCar类:

# car.py
class Car:
    # ... 代码省略 ...

class ElectricCar(Car):
    # ... 代码省略 ...
9.4.3 从一个模块中导入多个类

使用逗号分隔类名,可以从一个模块中导入多个类。
示例

from car import Car, ElectricCar  # 导入Car和ElectricCar类

my_beetle = Car("volkswagen", "beetle", 2024)
my_tesla = ElectricCar("tesla", "roadster", 2024)
9.4.4 导入整个模块

使用import 模块名导入整个模块,然后通过“模块名.类名”的方式使用类。
示例

import car  # 导入整个car模块

my_beetle = car.Car("volkswagen", "beetle", 2024)  # 通过模块名访问类
my_tesla = car.ElectricCar("tesla", "roadster", 2024)
9.4.5 导入模块中的所有类

使用from 模块名 import *可以导入模块中所有类(不推荐,可能导致命名冲突)。
示例

from car import *  # 导入car模块中所有类

my_beetle = Car("volkswagen", "beetle", 2024)
9.4.6 在一个模块中导入另一个模块

如果模块A中的类依赖模块B中的类,可以在模块A中导入模块B。
示例electric_car.py(电动车模块)依赖car.py(汽车模块):

# electric_car.py
from car import Car  # 导入Car类

class ElectricCar(Car):
    # ... 代码省略 ...

然后在主程序中可以直接导入ElectricCar

from electric_car import ElectricCar
9.4.7 使用别名

当类名或模块名过长时,可以用as指定别名,简化代码。
示例

from car import ElectricCar as EC  # 给类起别名EC
my_tesla = EC("tesla", "model s", 2024)

import car as c  # 给模块起别名c
my_car = c.Car("audi", "a4", 2024)
9.4.8 找到合适的工作流程

导入类的方式没有固定标准,需根据项目复杂度选择:

  • 小型项目:可将所有类放在主程序中。
  • 中型项目:将类拆分到多个模块,按需导入。
  • 大型项目:严格按功能划分模块,避免循环导入和命名冲突。

9.5 Python 标准库

Python 标准库是一组内置模块,包含大量实用的类和函数,可直接导入使用,无需手动编写。
示例random模块(生成随机数)、datetime模块(处理日期时间)、json模块(处理JSON数据)等。

from random import randint  # 从标准库random导入randint函数
print(randint(1, 6))  # 输出1-6之间的随机整数

9.6 类的编程风格

遵循良好的编程风格可提高代码可读性:

  • 类名使用“驼峰式命名法”(首字母大写,如CarElectricCar),不使用下划线。
  • 实例名和模块名使用小写字母,多个单词用下划线连接(如my_carcar_module)。
  • 每个类和方法都应包含文档字符串("""说明内容"""),描述其功能。
  • 若类的属性或方法仅在内部使用,可在名称前加下划线(如_internal_attr),表示“私有”(Python中无严格私有机制,仅为约定)。
  • 避免在类定义中添加无关功能,保持类的单一职责。

9.7 小结

  • 类是对象的模板,定义了对象的属性和方法;实例是类的具体实现。
  • __init__()方法用于初始化实例属性,self参数是实例本身的引用。
  • 继承允许子类复用父类的代码,并可扩展或重写父类功能。
  • 可将类拆分为多个模块,通过导入机制在主程序中使用,使代码更清晰。
  • Python 标准库提供了丰富的内置类和函数,可直接使用以提高开发效率。

通过掌握类与面向对象


总结

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值