Python类与对象基础:面向对象编程语法简明教程
面向对象编程(OOP)是Python组织复杂程序逻辑的核心方式。本文直接梳理Python中类(Class)与对象(Object)的核心语法,通过具体代码与机制解析,说明类的定义、实例化过程、__init__与self的作用原理、属性与方法的作用域差异,以及单继承的基础用法,帮助读者建立清晰准确的面向对象编程思维。
一、核心概念:从模板到实体
在面向过程的程序设计中,数据与处理数据的函数通常是分离的;而在面向对象编程中,类将相关联的数据(属性)与针对这些数据的操作(方法)统一打包封装成一个整体。
理解面向对象,关键在于区分“类”与“对象”:
- 类(Class):是创建对象的图纸或蓝本。它定义了该类型的所有实体应该具备哪些变量和能力,但本身不占用实体数据的内存空间。
- 对象 / 实例(Object / Instance):是根据类模板实际创建出来的具体存在。每个对象拥有独立的内存空间,用于存储属于自己的具体数据。
二、定义类与创建对象的基础语法
在Python中,定义类使用 class 关键字。按照PEP 8编码规范,类名通常使用大驼峰命名法(PascalCase),例如 BankAccount、DataParser。
创建类之后,像调用函数一样使用“类名加上圆括号”即可生成对象实例。以下是最简形态的类与其实例化代码:
# 示例:最简单的类定义与实例化
class SimpleUser:
pass # 使用 pass 作为空代码块占位
# 创建实例
u1 = SimpleUser()
u2 = SimpleUser()
print(u1) # 输出示例: <__main__.SimpleUser object at 0x104b2e8e0>
print(u2) # 输出示例: <__main__.SimpleUser object at 0x104b2e940>
print(u1 == u2) # 输出示例: False (两个独立的内存地址)
虽然 u1 与 u2 都是由 SimpleUser 创建的,但通过打印输出可以看到它们的内存地址不同,说明二者是系统分配的独立实体。
三、构造方法 __init__ 与 self 的机制
在实际编程中,我们极少创建空对象。对象在创建时通常需要携带专属的初始状态,这就需要用到构造方法 __init__。
1. __init__ 方法的作用
__init__ 是Python内置的特殊方法(Magic Method / Dunder Method)。当执行 obj = ClassName(...) 时,Python会自动调用该类的 __init__ 方法,将传入的参数绑定到新创建的对象上。
2. self 参数的本质
初学者最常疑惑的是:为什么每个实例方法的第一个参数都是 self?
self 代表的是当前正在被操作的具体实例本身。当执行 u1.get_balance() 时,Python解释器在底层实际执行的是 User.get_balance(u1)。显式声明 self 让方法内部能够精确知道该读写哪个对象的属性。
四、编写完整的类:方法与状态管理
下面通过一个包含状态修改与数据验证的完整类示例,展示属性定义、参数传递与实例方法的实际组合方式:
# 完整示例:银行账户管理类
class BankAccount:
def __init__(self, owner: str, initial_balance: float = 0.0):
# 绑定实例属性
self.owner = owner
self.balance = initial_balance
# 实例方法:存款
def deposit(self, amount: float) -> float:
if amount <= 0:
print("[错误] 存款金额必须大于0")
return self.balance
self.balance += amount
print(f"[成功] {self.owner} 存入 {amount} 元,当前余额: {self.balance} 元")
return self.balance
# 实例方法:取款
def withdraw(self, amount: float) -> float:
if amount > self.balance:
print(f"[错误] {self.owner} 余额不足,当前余额仅有 {self.balance} 元")
return self.balance
self.balance -= amount
print(f"[成功] {self.owner} 取出 {amount} 元,剩余余额: {self.balance} 元")
return self.balance
# 实例方法:打印简报
def describe(self) -> str:
return f"账户持有者: {self.owner} | 余额: {self.balance}"
# 运行代码
account_a = BankAccount("张三", 1000.0)
account_b = BankAccount("李四", 200.0)
account_a.deposit(500.0) # 输出: [成功] 张三 存入 500.0 元,当前余额: 1500.0 元
account_b.withdraw(300.0) # 输出: [错误] 李四 余额不足,当前余额仅有 200.0 元
在上述代码中,account_a 与 account_b 调用相同的方法名 deposit,但操作的是各自内存空间中的 self.balance,因此相互之间完全独立。
五、类属性 vs 实例属性:作用域与命名空间查找机制
Python对象的属性分为两大类,区分它们对避免数据污染至关重要:
- 实例属性(Instance Attribute):在方法内部通过
self.属性名赋值,专属于当前实例,存储在对象的__dict__字典中。 - 类属性(Class Attribute):直接定义在类体中、所有方法外部的变量,属于类本身,由所有该类的实例共同共享。
当通过对象读取属性(如 u1.bank_name)时,Python先在实例自身的属性字典中查找;如果未找到,则自动回溯到类属性字典中查找。
u1.bank_name = "工商银行",这并不会修改类的公共属性,而是在 u1 实例中悄悄新增了一个同名的“实例属性”,从而遮蔽了类属性。如果要修改类属性,必须通过类名操作,如 BankAccount.bank_name = "工商银行"。
六、面向对象进阶基础:继承与 super()
当多个类拥有相同的属性或方法时,可以通过继承复用代码,形成父子关系。子类自动拥有父类的所有公开属性与方法,并可以进行扩展或重写(Override)。
# 基类 (父类)
class Account:
def __init__(self, owner: str, balance: float):
self.owner = owner
self.balance = balance
def get_info(self):
return f"用户: {self.owner}, 余额: {self.balance}"
# 派生类 (子类):储蓄账户,增加利息机制
class SavingsAccount(Account):
def __init__(self, owner: str, balance: float, interest_rate: float = 0.03):
# 使用 super() 调用父类的 __init__ 方法,复用初始化逻辑
super().__init__(owner, balance)
self.interest_rate = interest_rate
# 新增子类专有方法
def apply_interest(self):
interest = self.balance * self.interest_rate
self.balance += interest
print(f"已计息 {interest:.2f} 元,最新余额: {self.balance:.2f} 元")
# 重写父类方法 (Override)
def get_info(self):
base_info = super().get_info()
return f"{base_info}, 年利率: {self.interest_rate * 100}%"
# 使用示例
sa = SavingsAccount("王五", 10000.0, 0.04)
print(sa.get_info()) # 输出: 用户: 王五, 余额: 10000.0, 年利率: 4.0%
sa.apply_interest() # 输出: 已计息 400.00 元,最新余额: 10400.00 元
七、面向对象基础知识全景总结
掌握Python面向对象编程的核心,在于理清类、实例、方法以及命名空间之间的交互链路。以下知识架构图总结了从语法入门到规范开发的核心路径:
通过掌握上述核心语法,读者即可在实际项目中灵活运用类来封装复杂的数据与业务逻辑。在后续进阶中,还可以进一步探索私有变量命名约定(单下划线与双下划线)、属性装饰器(@property)、类方法(@classmethod)以及特殊魔法方法(如 __str__、__repr__),构建更加健壮与优雅的面向对象系统。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









