Python类与对象基础语句:class定义、__init__与继承写法
深入讲解Python面向对象编程的核心基础语句,涵盖class定义语法、__init__构造初始化逻辑、单继承与super()协同写法,配合工程架构图示与易错避坑解析。
掌握面向对象编程(OOP)的核心在于理解数据与操作数据的逻辑如何封装在一起。在 Python 中,类(Class)是创建对象的模板蓝图,而对象(Object)是根据该蓝图生成的具体实体。本文直接切入面向对象最核心的三大基础语句:如何通过 class 声明类型与方法、如何借助 __init__ 构造方法规范化初始化对象属性,以及如何运用单继承结构与 super() 实现代码的高效复用与扩展。掌握这三项语法,便能从根本上建立起清晰严谨的面向对象编程思维。
一、class 关键字与类的基本定义
在 Python 中,定义一个类使用 class 关键字。按照 PEP 8 编程规范,类名通常采用大驼峰命名法(PascalCase),例如 UserAccount 或 DataProcessor。类体内可以包含属性(数据)和方法(函数)。在类中定义的普通函数被称为“实例方法”,其实参列表的首位必须显式保留一个参数,通常约定命名为 self。
# 基础类定义语法
class Dog:
# 类属性(所有实例共享)
species = "犬科"
# 实例方法:首个参数必须为 self
def set_name(self, name):
self.name = name # 将传入的数据绑定到具体实例上
def bark(self):
return f"{self.name} 正在汪汪叫!"
实例化与 self 的本质:实例化类只需要像调用函数一样在类名后添加圆括号。当执行 dog1 = Dog() 时,Python 会在堆内存中为该对象分配独立的内存空间;当调用 dog1.set_name("旺财") 时,Python 解释器在底层会自动把 dog1 这个实例本身作为第一个实参隐式传给 set_name 的 self。也就是说,dog1.bark() 在底层的实际执行等价于 Dog.bark(dog1)。
二、__init__ 构造方法与属性初始化
在前面的例子中,我们通过自定义的 set_name 方法为对象赋予属性,但这要求使用者在创建对象后必须手动调用一次配置方法,稍有遗忘就会导致对象状态不完整。Python 提供了专门的双下划线方法(特殊方法/魔术方法)——__init__,用于在对象被创建后立即自动执行初始化设置。
class Student:
# 构造初始化方法
def __init__(self, name, student_id, score=0):
# 属性绑定:将实参值赋给该实例独有的属性
self.name = name
self.student_id = student_id
self.score = score
def display_info(self):
return f"学号:{self.student_id} | 姓名:{self.name} | 分数:{self.score}"
# 创建实例时直接传参,自动触发 __init__
stu = Student("张三", "S202401", score=92)
print(stu.display_info()) # 输出:学号:S202401 | 姓名:张三 | 分数:92
理解 __init__ 的生命周期:很多初学者误以为 __init__ 是负责“创建”对象的方法,实际上在 Python 内部,对象的创建是由 __new__ 方法完成的。当执行 Student(...) 时,Python 解释器先调用 __new__ 在内存中开辟一个空白的实例空间,随后立即将这个空白实例作为 self 实参传递给 __init__。__init__ 的唯一职责是“填充和配置”这个实例的数据,相当于新房交付后的内部装修。
关键避坑点:__init__ 绝对不能显式返回值!在 Python 中,__init__ 必须返回 None(或者不写 return 语句)。如果你在 __init__ 中写了类似 return self.name 或 return 100,解释器在执行时会直接抛出严重的运行时异常:TypeError: __init__() should return None, not '...'。
三、类的继承写法与 super() 协同机制
当多个类具有相似或相同的属性和行为时,复制粘贴代码会导致系统难以维护。Python 通过继承(Inheritance)机制允许一个类(子类 / 派生类)从另一个类(父类 / 基类)继承所有非私有属性和方法。定义子类时,只需要在类名后使用小括号指定父类即可:class ChildClass(ParentClass):。
1. 方法重写与 super() 函数
如果子类继承了父类的方法,但希望实现属于自己的特定行为,只需在子类中定义同名方法,这就是方法重写(Method Overriding)。在重写方法时,如果希望保留并复用父类原有的逻辑,可以使用 super() 内置函数来代理调用父类的方法。
# 基类(父类)
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
return f"{self.name} 正在进食。"
def make_sound(self):
return "发出某种叫声"
# 派生类(子类)
class Cat(Animal):
def __init__(self, name, age, is_indoor=True):
# 1. 委托父类完成基础属性初始化
super().__init__(name, age)
# 2. 扩展子类专属属性
self.is_indoor = is_indoor
# 重写父类的 make_sound 方法
def make_sound(self):
return "喵喵喵~"
# 子类特有的扩展方法
def catch_mouse(self):
return f"{self.name} 抓到了一只老鼠!"
方法解析顺序(MRO)与属性查找流程:当我们在一个实例上调用 cat.eat() 时,Python 解释器会遵循方法解析顺序(Method Resolution Order,简称 MRO)沿着继承链查找该成员。首先检查 cat 实例自身的字典,未找到则检查 Cat 类的空间;Cat 类中没有定义 eat,解释器便自动沿继承链向上溯源到 Animal 类,并在那里成功找到并执行 eat 方法。如果整个继承链一直追溯到顶级基类 object 依然找不到,解释器才会抛出 AttributeError。
四、核心语句规范与高频易错避坑指南
初学者在编写面向对象代码时,最容易出现以下三类隐蔽错误。通过掌握其内在成因,可以在日常开发与代码审查中快速定位并修复:
1. 遗漏 self 参数或手动传入 self
在类内定义实例方法时,如果忘记在首位写 self(例如写成 def get_status():),当通过实例调用 obj.get_status() 时,Python 会自动将 obj 塞入首个实参,导致报出 TypeError: get_status() takes 0 positional arguments but 1 was given。反之,在外部调用方法时,直接调用 obj.get_status() 即可,千万不要手动写成 obj.get_status(obj)。
2. 可变对象误用为类属性导致的“数据串扰”
类属性是所有实例共享的内存空间。如果不小心将列表(list)、字典(dict)等可变类型定义为类属性,所有实例在对其进行修改时都会相互影响:
# 错误写法:可变对象作为类属性
class TeamBad:
members = [] # 危险!所有实例共享同一个列表对象
# 正确写法:在 __init__ 中为每个实例独立创建容器
class TeamGood:
def __init__(self):
self.members = [] # 正确!每个实例拥有专属独立的列表
3. 子类重写 __init__ 时遗漏 super().__init__()
如果子类重写了 __init__ 构造方法,而没有在方法体内显式调用 super().__init__(...),那么父类的初始化代码完全不会执行。随后访问任何由父类负责初始化的属性时,程序都会抛出 AttributeError。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









