Python面向对象编程代码示例:类与继承
本文通过完整、清晰的代码示例,详细讲解Python面向对象编程中类与继承的核心用法,包含类定义、self解析、单继承、super()调用机制及方法重写。
面向对象编程(OOP)通过将状态数据与操作逻辑封装在一起,帮助开发者构建高内聚、易复用的软件系统。在 Python 中,实现面向对象的核心是“类”(Class)与“继承”(Inheritance):类提供了创建对象的蓝图与方法规范,而继承则允许派生类在保留父类通用特性的同时定制专有行为。本文通过连贯的代码示例,直观展示 Python 中类的定义、实例化、__init__ 构造机制以及单继承与 super() 的具体实现方式。
一、类与对象的基础构建
在 Python 中,使用 class 关键字声明一个类。类内部通过 __init__ 初始化方法绑定实例专属的属性,所有实例方法的第一个参数约定为 self,它指代当前被操作的具体对象实例。
以下示例定义了一个通用的 Employee(员工)基类,包含工号、姓名、底薪三个属性,以及一个计算月薪与输出信息的标准方法:
# 定义基类:Employee
class Employee:
def __init__(self, emp_id: str, name: str, base_salary: float):
self.emp_id = emp_id
self.name = name
self.base_salary = base_salary
def calculate_pay(self) -> float:
# 基类默认返回基本薪资
return self.base_salary
def get_info(self) -> str:
return f"[{self.emp_id}] {self.name} | 实发月薪: ¥{self.calculate_pay():.2f}"
# 示例调用与实例化
e1 = Employee("E1001", "张三", 6500.0)
print(e1.get_info())
# 示例输出: [E1001] 张三 | 实发月薪: ¥6500.00
每次调用 Employee("E1001", "张三", 6500.0) 时,Python 会在内存中分配一块独立的空间存放实例属性,并将新对象的引用自动传递给 self,从而完成各实例属性的隔离。
二、使用继承扩展派生类
当业务系统需要支持不同岗位时,重复编写 emp_id 和 name 会带来大量冗余。继承语法允许我们在类名后添加括号,指定其父类:class Child(Parent):。
在子类的 __init__ 中,推荐使用 super().__init__(...) 调用父类的初始化方法,优先由父类完成公共属性的赋值,子类仅处理自身新增的专有属性。
三、方法重写与 super() 的协同工作
派生类可以重新定义与父类同名的方法,这被称为方法重写(Method Overriding)。在重写方法时,如果仅需要补充逻辑而非彻底推翻父类行为,依然可以通过 super().方法名() 调用父类的原逻辑。
下面的代码派生出两个具体的岗位类:Developer(软件开发工程师,拥有编程语言属性及项目绩效)与 Manager(项目经理,拥有管理团队与固定津贴):
# 派生类 1:Developer 继承自 Employee
class Developer(Employee):
def __init__(self, emp_id: str, name: str, base_salary: float, primary_lang: str, project_bonus: float):
# 1. 显式委托父类处理基础属性
super().__init__(emp_id, name, base_salary)
# 2. 绑定开发岗位特有属性
self.primary_lang = primary_lang
self.project_bonus = project_bonus
# 方法重写:薪资计算加入项目奖金
def calculate_pay(self) -> float:
base = super().calculate_pay()
return base + self.project_bonus
# 方法重写:信息展示增加主要技术栈
def get_info(self) -> str:
return f"[研发-{self.primary_lang}] {self.name} | 实发月薪: ¥{self.calculate_pay():.2f}"
# 派生类 2:Manager 继承自 Employee
class Manager(Employee):
def __init__(self, emp_id: str, name: str, base_salary: float, team_allowance: float):
super().__init__(emp_id, name, base_salary)
self.team_allowance = team_allowance
# 方法重写:薪资计算加入团队津贴
def calculate_pay(self) -> float:
return self.base_salary + self.team_allowance
def get_info(self) -> str:
return f"[管理团队] {self.name} | 实发月薪: ¥{self.calculate_pay():.2f}"
当对象调用 calculate_pay() 时,Python 会依据方法解析顺序(Method Resolution Order, MRO)从当前子类开始自底向上查找。如果在子类中找到了对应方法,则直接执行重写后的代码;子类代码中通过 super() 发起的调用,则会继续向上沿继承链检索父类版本。
四、多态:同一接口的多样化执行
继承不仅减少了模板代码的编写,更重要的是赋予了程序“多态”的能力。客户端代码无需关心当前员工究竟是普通员工、开发人员还是主管,只需直接调用统一约定的 get_info() 或 calculate_pay() 接口:
# 统一容器:存放不同类型的员工对象
staff_roster = [
Employee("E1001", "张三", 6000.0),
Developer("D2001", "李四", 12000.0, "Python", 3500.0),
Manager("M3001", "王五", 16000.0, 5000.0)
]
# 统一调用接口遍历结算
total_payout = 0.0
for member in staff_roster:
print(member.get_info())
total_payout += member.calculate_pay()
print(f"\n本月总预算支出: ¥{total_payout:.2f}")
# 示例输出:
# [E1001] 张三 | 实发月薪: ¥6000.00
# [研发-Python] 李四 | 实发月薪: ¥15500.00
# [管理团队] 王五 | 实发月薪: ¥21000.00
#
# 本月总预算支出: ¥42500.00
上述循环中,虽然 member 指向的真实类型各异,但调用接口的一致性使得上层逻辑非常精简。若日后新增 Designer(设计师)子类,只需继承 Employee 并按规则重写,外部的报表与薪酬计算逻辑完全无需修改。
五、面向对象与继承的常见误区及注意事项
避坑指南:
- 不要遗漏方法签名的
self参数:如果定义实例方法时未显式声明self,在通过实例调用时会抛出TypeError: ... takes 0 positional arguments but 1 was given异常。 - 子类构造器务必调用
super().__init__():子类如果定义了自己的__init__,父类的构造方法默认不会自动运行。若遗漏调用,继承自父类的属性将不会被创建,后续访问会抛出AttributeError。 - 谨防可变对象作为类属性:定义在类体直接赋值的列表或字典属于所有实例共享的类属性。若需要每个实例拥有独立列表,必须在
__init__中进行赋值绑定(例如self.tags = [])。 - 避免过深或过度复杂的继承层级:当两个类之间主要是“拥有(Has-A)”关系而非“属于(Is-A)”关系时,优先采用对象组合(Composition)而非继承。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













