Python 面向对象编程

2026年04月24日 21:08


一、类(Class

精准定义

类是面向对象编程(OOP)的核心抽象结构,是用于创建实例(对象)的模板,它封装了一组具有相同属性(特征)和方法(行为)的对象的共同特征。类本身不占用运行时内存,仅用于定义结构;只有通过实例化生成对象后,才会分配内存空间。

Python中,类通过class关键字定义,所有类默认继承自object类(Python 3中,即使不写class 类名(object):,也会隐式继承),支持封装、继承、多态三大核心特性,且允许动态添加/修改属性和方法。

场景化示例(贴合实际开发)

python
# 定义一个“学生”类,封装学生的共同属性(姓名、学号)和行为(选课、打印信息)
class Student(object):  # 显式继承object,规范写法
    # 类属性:所有学生共享的固定数据(学校名称)
    school = "北京大学"
    
    # 构造方法(初始化方法):实例化时自动调用,用于初始化实例属性
    # self是必选参数,代表当前创建的实例本身,不可省略
    def __init__(self, name, student_id):
        # 实例属性:每个学生独有的数据,通过self绑定到实例
        self.name = name          # 学生姓名(实例独有)
        self.student_id = student_id  # 学号(实例独有)
        self.courses = []         # 选课程列表(实例独有,初始为空)
    
    # 实例方法:描述学生的行为,第一个参数必须是self
    def choose_course(self, course_name):
        """学生选课的方法,将课程添加到选课程列表"""
        self.courses.append(course_name)
    
    def print_info(self):
        """打印学生的详细信息"""
        print(f"学号:{self.student_id},姓名:{self.name},学校:{self.school},已选课程:{self.courses}")

# 易错点提醒:1. __init__是双下划线(魔术方法),单下划线无效;2. self不可省略,也不能替换为其他名称(虽可自定义,但不符合规范)

二、实例(对象,Instance / Object

精准定义

实例(对象)是通过类实例化得到的具体实体,是类的具象化体现。每个实例都拥有类定义的属性和方法,但会有自己独立的实例属性值,占用独立的运行时内存,实例之间的属性互不干扰。

实例化语法:实例名 = 类名(参数),参数需与类的__init__方法中除self外的参数对应(无额外参数则不传)。

场景化示例(承接上面的Student类)

python
# 实例化:创建2个不同的学生实例(对象)
stu1 = Student("张三", "2024001")  # 传入name和student_id参数,触发__init__初始化
stu2 = Student("李四", "2024002")

# 访问实例属性:实例名.属性名
print(stu1.name)        # 输出:张三(仅属于stu1的实例属性)
print(stu2.student_id)  # 输出:2024002(仅属于stu2的实例属性)
print(stu1.school)      # 输出:北京大学(访问类属性,所有实例共享)

# 调用实例方法:实例名.方法名(参数)
stu1.choose_course("Python编程")
stu2.choose_course("高等数学")
stu2.choose_course("英语")

# 打印学生信息,体现实例属性的独立性
stu1.print_info()  # 输出:学号:2024001,姓名:张三,学校:北京大学,已选课程:['Python编程']
stu2.print_info()  # 输出:学号:2024002,姓名:李四,学校:北京大学,已选课程:['高等数学', '英语']

# 易错点提醒:实例不能直接调用类的魔术方法(如__init__),需通过类名调用(不推荐新手操作)

三、方法(Method

精准定义

方法是定义在类内部的函数,用于描述类或实例的行为,与普通函数的区别是:方法必须绑定到类或实例上才能调用,且有固定的默认第一个参数(self/cls)。Python中方法分为三类,用途明确,不可混淆。

1. 实例方法(最常用,核心)

绑定到实例的方法,第一个参数必须是self(代表当前实例),只能通过实例调用,可直接访问/修改实例属性和类属性。

python
# 承接Student类,新增实例方法(修改姓名)
class Student(object):
    school = "北京大学"
    def __init__(self, name, student_id):
        self.name = name
        self.student_id = student_id
    
    # 实例方法:修改实例属性name
    def update_name(self, new_name):
        self.name = new_name  # 通过self访问并修改实例属性

# 调用实例方法
stu1 = Student("张三", "2024001")
stu1.update_name("张三丰")
print(stu1.name)  # 输出:张三丰(实例属性已修改)

2. 类方法(@classmethod 装饰器)

绑定到类的方法,需用@classmethod装饰器修饰,第一个参数必须是cls(代表当前类),可通过类或实例调用,**只能访问/修改类属性,不能直接访问实例属性**(除非传入实例)。

python
class Student(object):
    school = "北京大学"  # 类属性
    count = 0  # 类属性:统计学生实例的数量
    
    def __init__(self, name, student_id):
        self.name = name
        self.student_id = student_id
        Student.count += 1  # 实例化时,类属性count自增
    
    # 类方法:修改类属性school,统计学生数量
    @classmethod
    def update_school(cls, new_school):
        cls.school = new_school  # 通过cls访问并修改类属性
    
    @classmethod
    def get_student_count(cls):
        return cls.count  # 通过cls访问类属性

# 调用类方法(两种方式,推荐用类名调用)
Student.update_school("清华大学")  # 类调用
stu1 = Student("张三", "2024001")
stu1.update_school("复旦大学")    # 实例调用(不推荐,语义不清晰)

print(Student.school)  # 输出:复旦大学(类属性已修改)
print(stu1.school)     # 输出:复旦大学(所有实例共享类属性)
print(Student.get_student_count())  # 输出:1(统计实例数量)

# 易错点提醒:类方法不能直接访问self.xxx(实例属性),会报错

3. 静态方法(@staticmethod 装饰器)

不绑定到类或实例的方法,需用@staticmethod装饰器修饰,**无默认参数(无self/cls**,本质是放在类里的普通函数,不能直接访问类属性和实例属性(除非手动传入类/实例),仅用于封装与类相关的工具函数。

python
class Student(object):
    school = "北京大学"
    
    # 静态方法:工具函数,判断学号是否合法(仅与学生类相关,无依赖)
    @staticmethod
    def is_valid_student_id(student_id):
        # 无self/cls,不能直接访问school或实例属性
        return len(student_id) == 6 and student_id.startswith("2024")

# 调用静态方法(两种方式,均可)
print(Student.is_valid_student_id("2024001"))  # 输出:True(合法)
print(Student.is_valid_student_id("202401"))   # 输出:False(不合法)

stu1 = Student("张三", "2024001")
print(stu1.is_valid_student_id("2024002"))     # 输出:True

# 易错点提醒:静态方法不能直接使用self/cls,若需访问类/实例属性,需手动传入

四、类属性(Class Attribute / Class Variable

精准定义

类属性是定义在**类内部、所有方法外部**的属性,属于类本身,**所有实例共享同一份数据**,内存中仅存储一份,修改类属性会影响所有实例对该属性的访问结果。

用途:存储所有实例共用的固定数据(如学校名称、默认配置、计数器等),避免重复创建相同数据,节省内存。

场景化示例(区分类属性修改实例属性覆盖

python
class Teacher(object):
    # 类属性:所有老师共享
    department = "计算机学院"  # 院系
    salary_base = 8000        # 基础工资
    
    def __init__(self, name):
        self.name = name  # 实例属性:老师姓名

# 1. 访问类属性(类、实例均可访问)
print(Teacher.department)  # 输出:计算机学院(类访问,推荐)
t1 = Teacher("王老师")
print(t1.department)       # 输出:计算机学院(实例访问,本质是访问类属性)

# 2. 修改类属性(只能通过类名修改,实例修改会创建新的实例属性,覆盖类属性)
Teacher.salary_base = 9000  # 类修改类属性,所有实例生效
t2 = Teacher("李老师")
print(t1.salary_base)  # 输出:9000(生效)
print(t2.salary_base)  # 输出:9000(生效)

# 3. 易错点:实例“修改”类属性(实际是创建实例属性,覆盖类属性,不影响其他实例和类)
t1.department = "软件学院"  # 给t1创建实例属性department,覆盖类属性
print(t1.department)        # 输出:软件学院(实例属性)
print(t2.department)        # 输出:计算机学院(类属性,未被修改)
print(Teacher.department)   # 输出:计算机学院(类属性,未被修改)

五、实例属性(Instance Attribute / Instance Variable

精准定义

实例属性是绑定在实例(self)上的属性,通常在__init__方法中通过self.属性名 = 值定义,也可在实例创建后动态添加。每个实例拥有独立的实例属性副本,内存中单独存储,实例之间的实例属性互不干扰。

用途:存储每个实例独有的个性化数据(如姓名、学号、年龄等)。

场景化示例(动态添加/修改/删除实例属性)

python
class Book(object):
    # 类属性:所有书籍共享
    type = "纸质书"
    
    # __init__中定义实例属性
    def __init__(self, title, author):
        self.title = title  # 书名(实例独有)
        self.author = author  # 作者(实例独有)

# 1. 实例化,初始化实例属性
book1 = Book("Python编程:从入门到精通", "张三")
book2 = Book("数据结构与算法", "李四")

# 2. 访问实例属性
print(book1.title)  # 输出:Python编程:从入门到精通
print(book2.author) # 输出:李四

# 3. 动态添加实例属性(实例创建后,额外添加属性)
book1.price = 59.9  # 给book1添加实例属性price
# print(book2.price)  # 报错:book2没有price属性(实例属性独立)

# 4. 动态修改实例属性
book1.author = "张三丰"
print(book1.author)  # 输出:张三丰

# 5. 删除实例属性(del关键字)
del book1.price
# print(book1.price)  # 报错:price已被删除

# 易错点提醒:实例属性仅属于当前实例,不能通过一个实例修改另一个实例的属性

六、局部变量(Local Variable

精准定义

局部变量是定义在**方法内部**(包括实例方法、类方法、静态方法)的变量,作用域仅限于当前方法,**方法执行开始时创建,方法执行结束后自动销毁**,无法被类的其他方法、实例或外部代码访问。

用途:用于方法内部的临时计算、中间结果存储,不影响类和实例的属性。

场景化示例(明确局部变量的作用域)

python
class Calculator(object):
    # 类属性
    pi = 3.14159
    
    # 实例方法:计算圆的面积
    def circle_area(self, radius):
        # 局部变量:仅在circle_area方法内部有效
        square_radius = radius * radius  # 临时计算半径的平方
        area = self.pi * square_radius   # 临时计算面积
        return area  # 返回局部变量的值

# 调用方法
calc = Calculator()
print(calc.circle_area(5))  # 输出:78.53975(正常返回)

# 易错点:外部无法访问局部变量
# print(square_radius)  # 报错:name 'square_radius' is not defined
# print(area)           # 报错:name 'area' is not defined

# 补充:局部变量与实例属性的区别(避免混淆)
def test_method(self):
    temp = 10  # 局部变量(方法内有效)
    self.temp = 20  # 实例属性(实例内有效)

七、继承(Inheritance

精准定义

继承是面向对象编程的核心复用机制,允许子类(派生类,Derived Class)继承父类(基类,Base Class)的所有非私有属性和方法,子类无需重复定义,同时可扩展新的属性/方法,或重写父类的方法以实现个性化功能。

Python支持单继承(一个子类继承一个父类)和多继承(一个子类继承多个父类,语法:class 子类名(父类1, 父类2, ...):),遵循方法解析顺序(MRO查找属性/方法。

关键术语:父类(基类)、子类(派生类)、重写(Override,子类重新定义父类的方法)、继承链(多个继承关系形成的链条)。

场景化示例(单继承+重写+扩展)

python
# 父类:动物类(封装所有动物的共同属性和行为)
class Animal(object):
    def __init__(self, name, age):
        self.name = name  # 所有动物都有姓名
        self.age = age    # 所有动物都有年龄
    
    # 父类方法:所有动物的共同行为(进食)
    def eat(self):
        print(f"{self.name}正在进食...")

# 子类:猫类(继承Animal,扩展自己的行为,重写父类方法)
class Cat(Animal):  # 继承Animal,Cat是子类,Animal是父类
    # 扩展新的实例属性(猫独有的“毛色”)
    def __init__(self, name, age, color):
        # 调用父类的__init__方法,复用父类的属性初始化(避免重复代码)
        super().__init__(name, age)  # 推荐用super(),兼容多继承
        # 新增子类的实例属性
        self.color = color
    
    # 重写父类的eat方法(猫的进食行为与普通动物不同)
    def eat(self):
        print(f"{self.color}的{self.name}({self.age}岁)正在吃猫粮...")
    
    # 扩展新的方法(猫独有的行为:喵喵叫)
    def meow(self):
        print(f"{self.name}喵喵叫~")

# 子类:狗类(继承Animal,仅重写方法,不扩展新属性)
class Dog(Animal):
    # 重写父类的eat方法
    def eat(self):
        print(f"{self.name}({self.age}岁)正在吃狗粮...")

# 测试继承、重写、扩展
cat1 = Cat("小白", 2, "白色")
cat1.eat()    # 输出:白色的小白(2岁)正在吃猫粮...(重写后的方法)
cat1.meow()   # 输出:小白喵喵叫~(扩展的方法)
print(cat1.color)  # 输出:白色(扩展的属性)

dog1 = Dog("大黄", 3)
dog1.eat()    # 输出:大黄(3岁)正在吃狗粮...(重写后的方法)

# 易错点提醒:1. 子类重写__init__时,必须调用父类的__init__(否则父类属性无法初始化);2. super()无需传入self,自动绑定

八、核心逻辑梳理(精准连贯)

1. :定义模板,封装所有实例的共同属性(类属性)和行为(方法),不占用运行时内存,是实例化的基础。

2. 实例(对象):类的具象化产物,通过实例化创建,占用独立内存,拥有自己的实例属性,可调用类的方法,是程序运行时实际操作的实体。

3. 类属性:属于类,所有实例共享,用于存储共用数据,仅能通过类名修改。

4. 实例属性:属于实例,每个实例独立拥有,用于存储个性化数据,可动态添加/修改/删除。

5. 方法:类/实例的行为,分三类——实例方法(操作实例)、类方法(操作类)、静态方法(工具函数),各有固定用途,不可混淆。

6. 局部变量:方法内部的临时变量,作用域仅限于方法,执行完毕后销毁,与类/实例属性无关。

7. 继承:实现代码复用,子类继承父类的非私有成员,可重写父类方法、扩展新功能,形成继承链。

核心关系:类 实例化 对象;类属性(共享)+ 实例属性(独立)对象的特征;方法 对象/类的行为;继承 扩展与复用。

补充:关键易错点汇总(必看)

 self是实例方法的第一个必选参数,代表当前实例;cls是类方法的第一个必选参数,代表当前类,不可省略。

 类属性只能通过类名修改,实例修改类属性会创建新的实例属性,覆盖类属性(不影响其他实例和类)。

 子类重写__init__时,必须通过super()调用父类的__init__,否则父类的属性无法初始化。

 局部变量仅在方法内部有效,外部无法访问;实例属性可通过实例访问,类属性可通过类/实例访问。

 静态方法无self/cls参数,不能直接访问类/实例属性;类方法不能直接访问实例属性。