本文目录导读:

在 Python 中,构造方法(也称为构造函数)是 __init__ 方法,它在创建类的实例时自动调用,主要用于初始化对象的属性。
📌 基本语法和使用
最简单的构造方法
class Person:
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age # 实例属性
# 创建对象时自动调用 __init__
p = Person("小明", 25)
print(p.name) # 输出:小明
print(p.age) # 输出:25
🎯 常见使用场景和案例
1️⃣ 带默认参数的构造方法
class Student:
def __init__(self, name, grade="一年级", score=0):
self.name = name
self.grade = grade
self.score = score
def show_info(self):
print(f"学生:{self.name},{self.grade},成绩:{self.score}")
# 使用默认参数
s1 = Student("小李")
s2 = Student("小王", "三年级")
s3 = Student("小张", "五年级", 95)
s1.show_info() # 学生:小李,一年级,成绩:0
s2.show_info() # 学生:小王,三年级,成绩:0
s3.show_info() # 学生:小张,五年级,成绩:95
2️⃣ 计算属性(处理传入的数据)
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
self.area = width * height # 自动计算面积
self.perimeter = 2 * (width + height) # 自动计算周长
rect = Rectangle(5, 3)
print(f"面积:{rect.area}") # 输出:面积:15
print(f"周长:{rect.perimeter}") # 输出:周长:16
3️⃣ 数据验证和初始化处理
class BankAccount:
def __init__(self, account_no, balance=0):
# 验证账户号码
if not isinstance(account_no, str) or len(account_no) != 10:
raise ValueError("账户号码必须是10位字符串")
# 验证余额
if balance < 0:
raise ValueError("余额不能为负数")
self.account_no = account_no
self.balance = balance
self.transactions = [] # 初始化交易记录
def deposit(self, amount):
self.balance += amount
self.transactions.append(f"存款:+{amount}")
# 正确使用
acc = BankAccount("1234567890", 1000)
print(acc.balance) # 输出:1000
# 错误使用会抛出异常
# acc2 = BankAccount("123", 500) # 抛出 ValueError
4️⃣ 可变默认值的处理(重要!)
class ShoppingCart:
# ❌ 错误方式:不要用可变对象作为默认参数
# def __init__(self, items=[]):
# ✅ 正确方式:使用 None 然后判断
def __init__(self, items=None):
self.items = items if items is not None else []
self.total = 0
def add_item(self, item, price):
self.items.append(item)
self.total += price
# 测试
cart1 = ShoppingCart()
cart1.add_item("苹果", 5)
cart2 = ShoppingCart()
cart2.add_item("香蕉", 3)
print(cart1.items) # 输出:['苹果']
print(cart2.items) # 输出:['香蕉'] (不会受cart1影响)
5️⃣ 类继承中的构造方法
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
pass
class Dog(Animal):
def __init__(self, name, age, breed):
# 调用父类的构造方法
super().__init__(name, age)
self.breed = breed # 子类独有的属性
def speak(self):
return "汪汪!"
class Cat(Animal):
def __init__(self, name, age, color):
# 另一种调用方式
Animal.__init__(self, name, age)
self.color = color
def speak(self):
return "喵喵!"
# 使用
dog = Dog("大黄", 3, "金毛")
cat = Cat("小花", 2, "橘色")
print(f"{dog.name}说:{dog.speak()}") # 大黄说:汪汪!
print(f"{cat.name}说:{cat.speak()}") # 小花说:喵喵!
6️⃣ 单例模式(控制实例化)
class DatabaseConnection:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, host=None, port=None):
# 只在第一次实例化时初始化
if not hasattr(self, '_initialized'):
self.host = host
self.port = port
self._initialized = True
self._connect()
def _connect(self):
print(f"连接到数据库 {self.host}:{self.port}")
# 使用 - 确保只有一个数据库连接
db1 = DatabaseConnection("localhost", 3306)
db2 = DatabaseConnection("remote", 5432)
print(db1 is db2) # True(同一个实例)
print(db1.host, db2.host) # localhost localhost(没被覆盖)
💡 重要注意事项
__init__ vs __new__
class Demo:
def __new__(cls, *args, **kwargs):
# 创建对象(先执行)
print("1. __new__ 被调用")
instance = super().__new__(cls)
return instance
def __init__(self, value):
# 初始化对象(后执行)
print("2. __init__ 被调用")
self.value = value
d = Demo(10)
# 输出:
# 1. __new__ 被调用
# 2. __init__ 被调用
构造方法不能返回值(除了None)
class WrongDemo:
def __init__(self):
return "错误" # ❌ TypeError: __init__() should return None
class CorrectDemo:
def __init__(self):
pass # 正确:不显式返回或返回None
| 特性 | 说明 |
|---|---|
| 自动调用 | 创建对象时自动执行 |
| 初始化属性 | 最常用,设置实例的初始状态 |
| 参数传递 | 可以带参数,支持默认值 |
| 返回值 | 必须返回 None |
| 继承 | 子类需要调用父类的 __init__ |
| 执行顺序 | __new__ 先于 __init__ |
最佳实践:
- 使用
__init__进行属性初始化 - 避免在
__init__中做耗时操作 - 合理使用参数验证
- 注意可变默认参数的问题