程序员文章、书籍推荐和程序员创业信息与资源分享平台

网站首页 > 技术文章 正文

Python类从入门到精通,一篇就够!

hfteth 2025-04-29 00:38:25 技术文章 13 ℃

一、Python 类是什么?

大家在生活中应该都见过汽车吧,每一辆真实存在、能在路上跑的汽车,都可以看作是一个 “对象”。那这些汽车是怎么生产出来的呢?其实,在生产之前,汽车公司都会先设计一个详细的蓝图,这个蓝图里规定了汽车的各种特征,比如有几个轮子、车身是什么形状、用什么类型的发动机等等 ,而这个蓝图,就相当于我们 Python 中的 “类”。

简单来说,类就是一种抽象的模板或者蓝图,它定义了一类对象共有的属性(数据)和方法(行为)。属性就像是汽车的颜色、品牌、型号这些特征,而方法则像是汽车的启动、加速、刹车这些操作。通过类这个模板,我们可以创建出一个个具体的对象,这个过程就叫做 “实例化”,就好比按照汽车蓝图生产出一辆辆真实的汽车。在 Python 里,类是面向对象编程(OOP)的核心概念,理解和掌握类的使用,能让我们编写出更高效、更易维护的代码。

二、为什么要学 Python 类?

掌握 Python 类,能够为我们带来诸多好处。

先来说说代码的可维护性。想象一下,你参与开发一个大型的电商项目,里面涉及到商品、用户、订单等各种复杂的信息和操作。如果不使用类,所有的代码可能会像一团乱麻一样交织在一起,当需要修改某个功能,比如修改计算商品折扣的逻辑时,你可能得在一大段混乱的代码里大海捞针,而且一不小心就可能影响到其他功能 。但如果使用类,我们可以把商品相关的属性(如商品名称、价格、库存等)和方法(如计算折扣、更新库存等)封装在一个商品类里,用户相关的信息和操作封装在用户类里。这样代码结构清晰,当需要修改商品的某个功能时,直接找到商品类进行修改就行,大大降低了维护的难度。

再讲讲可扩展性。假设你正在开发一款游戏,最开始只有一种角色,比如战士,战士有自己的属性(生命值、攻击力等)和技能(挥砍、冲锋等) ,你可以把这些属性和技能封装在战士类中。随着游戏的发展,你想要增加新的角色,比如法师。由于使用了类,你只需要创建一个法师类,让它继承战士类的一些通用属性和方法(比如都有生命值,都能移动),然后再添加法师特有的属性(魔法值)和技能(释放火球术、治疗术等)就可以了,非常方便扩展。

此外,类还能实现代码复用。还是以游戏开发为例,游戏里可能有很多不同的怪物,它们都有一些共同的属性,比如生命值、攻击力,也有共同的行为,比如受到攻击会掉血、死亡时会有特效。我们就可以把这些共同的部分提取出来,放在一个怪物类里,然后各种具体的怪物类,像哥布林、骷髅怪,都继承这个怪物类,这样就避免了重复编写相同的代码,提高了开发效率 。

总的来说,学习 Python 类能让我们编写出更健壮、更灵活、更易于管理的代码,无论是小型项目还是大型企业级应用,都离不开类的使用,掌握它对我们的编程能力提升有着至关重要的作用。

三、Python 类基础语法

(一)类的定义

在 Python 中,使用class关键字来定义类 ,基本语法结构如下:


class ClassName:
    # 类属性(所有实例共享)
    class_attribute = value
    
    # 构造方法(初始化对象)
    def __init__(self, parameter1, parameter2, ...):
        # 实例属性(每个实例独有)
        self.attribute1 = parameter1
        self.attribute2 = parameter2
    
    # 实例方法
    def method_name(self, parameter1, parameter2, ...):
        # 方法体
        pass
    
    # 类方法(使用 @classmethod 装饰器)
    @classmethod
    def class_method_name(cls, parameter1, parameter2, ...):
        # 方法体
        pass
    
    # 静态方法(使用 @staticmethod 装饰器)
    @staticmethod
    def static_method_name(parameter1, parameter2, ...):
        # 方法体
        pass

在这里,ClassName是你定义的类的名称,一般采用大写字母开头的命名方式,遵循 “驼峰式命名法” ,这样可以增强代码的可读性,让人一眼就能区分出类名和其他变量名。比如我们定义一个表示狗狗的类Dog:

class Dog:
    # 类属性,所有狗都属于犬科
    species = "Canis familiaris"

    # 构造方法,初始化每只狗的名字和年龄
    def __init__(self, name, age):
        # 实例属性,每只狗都有自己独特的名字和年龄
        self.name = name
        self.age = age

    # 实例方法,让狗发出叫声
    def bark(self):
        return f"{self.name} says woof!"

    # 类方法,获取狗所属的物种
    @classmethod
    def get_species(cls):
        return f"Species: {cls.species}"

    # 静态方法,判断狗是否是幼犬
    @staticmethod
    def is_puppy(age):
        return age < 2


在这个例子中,Dog类有一个类属性species,表示所有狗都属于 “Canis familiaris” 这个物种 。__init__方法是构造方法,当我们创建Dog类的实例时,会自动调用这个方法来初始化实例的属性,像name和age就是每只狗独有的实例属性。bark方法是实例方法,通过self参数可以访问实例的属性,从而让每只狗都能以自己的名字发出叫声。get_species是类方法,通过cls参数访问类属性,返回狗所属的物种 。is_puppy是静态方法,它不需要访问类或实例的属性,只根据传入的年龄参数判断是否是幼犬。

(二)属性和方法

  1. 属性:类属性是定义在类中,并且在函数体外的属性,它可以在类的所有实例之间共享值 。比如上面Dog类中的species属性,所有Dog类的实例都共享这个属性,表示它们都属于犬科。我们可以通过类名直接访问类属性,如Dog.species ,也可以通过类的实例访问,如my_dog = Dog("Buddy", 3),然后my_dog.species同样可以访问到这个类属性。

实例属性通常在__init__方法或其他类方法中使用self关键字定义,每个实例都有自己独立的一份 。像Dog类中的name和age属性,每只狗都有自己不同的名字和年龄,这就是实例属性的特点。我们只能通过实例来访问实例属性,例如my_dog.name和my_dog.age ,如果尝试通过类名Dog.name或Dog.age访问,就会报错。

  1. 方法:类中方法的定义和普通函数类似,不过实例方法的第一个参数必须是self ,它代表了当前对象的实例,通过self我们可以访问和修改对象的属性。以Dog类中的bark方法为例:
def bark(self):
    return f"{self.name} says woof!"


这里的self参数允许我们在方法中使用每只狗独有的name属性,从而让每只狗都能以自己的名字发出叫声。当我们创建Dog类的实例并调用bark方法时,比如my_dog.bark() ,Python 会自动将my_dog这个实例作为self参数传递给方法。

方法的调用也很简单,对于实例方法,需要通过类的实例来调用 。就像前面提到的my_dog.bark() ,my_dog是Dog类的一个实例,通过它来调用bark方法。对于类方法,既可以通过类名调用,如Dog.get_species() ,也可以通过实例调用,如my_dog.get_species() ,不过一般更推荐使用类名调用,这样代码的意图更清晰 。静态方法同样既可以通过类名调用,如Dog.is_puppy(1) ,也可以通过实例调用,如my_dog.is_puppy(1) ,因为静态方法与类和实例的属性都无关,所以使用哪种方式调用主要取决于代码的可读性和一致性。

四、深入理解类的特性

(一)封装

封装,简单来说,就是把数据和对数据的操作 “打包” 在一起,同时限制外部对内部数据的直接访问,就好像把东西放进一个盒子里,然后只提供特定的 “开口”(接口)来操作里面的东西 。在 Python 中,通过在类中定义属性和方法来实现封装。比如,我们有一个BankAccount类来表示银行账户:

class BankAccount:
    def __init__(self, balance=0):
        # 这里使用双下划线开头的属性名,将余额属性设为私有
        self.__balance = balance  

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            print(f"Deposited {amount}. New balance: {self.__balance}")
        else:
            print("Deposit amount must be positive")

    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            print(f"Withdrew {amount}. New balance: {self.__balance}")
        else:
            print("Invalid withdraw amount")




在这个例子中,__balance是一个私有属性,在属性名前加上双下划线__ ,这是 Python 的一种命名约定,表示这个属性不应该在类的外部直接访问。外部代码想要操作账户余额,只能通过类提供的deposit和withdraw这两个公共方法,这就实现了数据的封装 。封装的好处是多方面的,一方面它保护了数据的安全性,避免外部代码随意修改账户余额,比如如果外部可以直接修改__balance ,就可能出现把余额改成负数等不合理的情况 ;另一方面,它实现了代码的模块化,将账户相关的操作都封装在BankAccount类中,使得代码结构更清晰,维护起来也更方便。

(二)继承

  1. 基本继承:继承就像是孩子继承父母的特征,在 Python 中,一个子类可以继承其父类的属性和方法 。创建子类时,在类名后面的括号中指定父类。比如,我们有一个Animal类作为父类,然后创建一个Dog类继承自Animal:
class Animal:
    def __init__(self, name):
        self.name = name

    def eat(self):
        print(f"{self.name} is eating.")


class Dog(Animal):
    def bark(self):
        print(f"{self.name} is barking.")


my_dog = Dog("Buddy")
my_dog.eat()  
my_dog.bark() 



在这个例子中,Dog类继承了Animal类,所以Dog类的实例my_dog可以使用Animal类中定义的eat方法,同时Dog类还拥有自己特有的bark方法 。通过继承,我们避免了重复编写Animal类中已有的属性和方法,提高了代码的复用性。

  1. 方法重写:当子类需要对父类的方法进行修改或定制时,就可以使用方法重写 。方法重写就是在子类中定义一个与父类同名的方法,这样在调用该方法时,会优先执行子类中的方法 。比如,我们再创建一个XiaoTianQuan类继承自Dog类,并重写bark方法:
class XiaoTianQuan(Dog):
    def bark(self):
        print(f"{self.name} is barking loudly like a god!")


xtq = XiaoTianQuan("XiaoTian")
xtq.eat()  
xtq.bark() 


这里XiaoTianQuan类重写了Dog类的bark方法,所以当调用xtq.bark()时,执行的是XiaoTianQuan类中重写后的bark方法,输出的是 “XiaoTian is barking loudly like a god!” ,而不是Dog类中原来的bark方法的输出。方法重写使得子类可以根据自身的需求,灵活地改变从父类继承来的方法的行为。

(三)多态

多态是指同一个方法调用,在不同的对象上会产生不同的行为 ,就好像同样是 “叫” 这个动作,狗叫和猫叫的声音是不一样的 。在 Python 中,多态通过方法重写和动态绑定来实现。比如,我们有一个Animal类,以及继承自它的Dog类和Cat类,它们都重写了make_sound方法:

class Animal:
    def make_sound(self):
        print("The animal makes a sound.")


class Dog(Animal):
    def make_sound(self):
        print("Woof! Woof!")


class Cat(Animal):
    def make_sound(self):
        print("Meow! Meow!")


def animal_sound(animal):
    animal.make_sound()


dog = Dog("Buddy")
cat = Cat("Mimi")

animal_sound(dog)  
animal_sound(cat) 



在这个例子中,animal_sound函数接受一个animal参数,它可以是Animal类的任何子类的实例 。当我们分别将Dog类的实例dog和Cat类的实例cat传递给animal_sound函数时,虽然调用的都是make_sound方法,但由于dog和cat是不同类的对象,它们重写后的make_sound方法实现不同,所以会产生不同的输出,这就是多态的体现 。多态的好处是提高了代码的灵活性和可扩展性,我们可以用统一的方式处理不同类型的对象,而不需要为每个对象类型单独编写处理逻辑。

五、实战演练

现在,让我们通过一个实战项目来巩固所学的 Python 类知识,我们将创建一个简单的学生管理系统类 。这个系统需要能够实现添加学生信息、查询学生信息、修改学生信息和删除学生信息的功能。

首先,我们来定义Student类,用于表示学生的基本信息:

class Student:
    def __init__(self, student_id, name, age, major):
        self.student_id = student_id
        self.name = name
        self.age = age
        self.major = major


在这个Student类中,__init__方法用于初始化学生对象的属性,包括学号student_id、姓名name、年龄age和专业major 。每个学生对象都有自己独立的这些属性值。

接着,我们定义StudentManagementSystem类,来管理学生信息,实现各种操作功能:

class StudentManagementSystem:
    def __init__(self):
        self.students = {}

    def add_student(self, student):
        if student.student_id in self.students:
            print(f"学号为 {student.student_id} 的学生已经存在。")
        else:
            self.students[student.student_id] = student
            print(f"学生 {student.name} 添加成功。")

    def search_student(self, student_id):
        if student_id in self.students:
            student = self.students[student_id]
            print(f"学号: {student.student_id}, 姓名: {student.name}, 年龄: {student.age}, 专业: {student.major}")
        else:
            print(f"学号为 {student_id} 的学生不存在。")

    def update_student(self, student_id, name=None, age=None, major=None):
        if student_id in self.students:
            student = self.students[student_id]
            if name:
                student.name = name
            if age:
                student.age = age
            if major:
                student.major = major
            print(f"学号为 {student_id} 的学生信息更新成功。")
        else:
            print(f"学号为 {student_id} 的学生不存在。")

    def delete_student(self, student_id):
        if student_id in self.students:
            del self.students[student_id]
            print(f"学号为 {student_id} 的学生删除成功。")
        else:
            print(f"学号为 {student_id} 的学生不存在。")







在StudentManagementSystem类中:

  • __init__方法初始化了一个空字典self.students ,用于存储学生对象,以学号作为字典的键,学生对象作为值 。
  • add_student方法用于添加学生,如果要添加的学生学号已经存在于self.students字典中,就提示学生已存在;否则,将学生对象添加到字典中,并提示添加成功 。
  • search_student方法根据传入的学号查询学生信息,如果学号存在,就打印出学生的详细信息;如果不存在,就提示学生不存在 。
  • update_student方法可以更新学生的信息,通过传入学号找到对应的学生对象,然后根据传入的新的姓名name、年龄age或专业major来更新学生对象的属性 ,并提示更新成功;如果学号不存在,就提示学生不存在 。
  • delete_student方法根据学号删除学生信息,如果学号存在,就从self.students字典中删除对应的学生对象,并提示删除成功;如果不存在,就提示学生不存在 。

最后,我们可以编写主程序来测试这个学生管理系统:

if __name__ == "__main__":
    system = StudentManagementSystem()

    # 添加学生
    student1 = Student("001", "Alice", 20, "Computer Science")
    system.add_student(student1)

    # 查询学生
    system.search_student("001")

    # 更新学生信息
    system.update_student("001", age=21)

    # 再次查询学生,验证更新结果
    system.search_student("001")

    # 删除学生
    system.delete_student("001")

    # 查询已删除的学生,验证删除结果
    system.search_student("001")




在主程序中,首先创建了StudentManagementSystem类的实例system 。然后创建了一个Student类的实例student1 ,并使用system.add_student方法将其添加到系统中 。接着通过system.search_student方法查询刚添加的学生信息 。之后使用system.update_student方法更新学生的年龄信息 ,再次查询学生信息来验证更新是否成功 。最后使用system.delete_student方法删除学生,并再次查询已删除的学生,验证删除操作是否生效 。通过这样一系列的操作,我们就可以完整地测试学生管理系统类的各项功能。

六、总结与展望

到这里,我们关于 Python 类的入门之旅就暂告一段落啦!回顾一下,我们从 Python 类的基本概念出发,了解到类就像是创建对象的蓝图 ,它定义了对象的属性和方法。接着深入学习了类的基础语法,包括类的定义,属性和方法的使用,明白了类属性是所有实例共享的,而实例属性每个实例都有自己独特的一份 ,实例方法通过self参数访问实例属性,类方法通过cls参数访问类属性,静态方法与类和实例属性都无关。

随后,我们探究了类的重要特性:封装,它将数据和操作封装在一起,保护数据安全并实现代码模块化;继承,使得子类可以复用父类的属性和方法,还能通过方法重写定制自己的行为;多态,同一个方法调用在不同对象上产生不同行为,让代码更加灵活和可扩展 。最后通过实战项目,我们亲手打造了一个简单的学生管理系统类,将所学知识运用到实际场景中,进一步加深了对 Python 类的理解和掌握 。

不过,Python 类的知识海洋还很广阔,比如元类、描述符这些更高级的概念等待着大家去探索。希望大家能以这篇教程为基石,在后续的学习中,不断实践,多阅读优秀的代码示例,积极参与开源项目。相信在不久的将来,你一定能熟练运用 Python 类,编写出高质量、可维护的代码,在 Python 编程的世界里大显身手!

Tags:

最近发表
标签列表