Python中的 __init__、__new__ 和 __call__示例详解
目录
- 1.__init__方法:对象初始化器
- 2.__new__方法:对象创建器
- 3.__call__方法:对象调用器
- 三者的协作流程
- 关键对比表
- 高级应用场景
- 1. 不可变类型扩展
- 2. 对象工厂
- 3. 带状态的装饰器
- 常见陷阱与解决方案
- 1. __init__ 中忘记返回 None
- 2.__new__ 忘记返回实例
- 3.单例模式中的重复初始化
- 4.__call__ 与 __init__ 参数混淆
- 总结
这三个特殊方法是 python 面向对象编程中的核心构造机制,分别在对象生命周期的不同阶段发挥作用:
1.__init__方法:对象初始化器
作用:初始化新创建的实例对象
调用时机:在
__new__
创建实例之后自动调用参数:第一个参数必须是
self
(指向新实例)返回值:无(必须返回
None
)核心职责:
设置实例属性的初始值
执行必要的初始化操作
不负责创建对象本身
class Person: def __init__(self, name, age): print("__init__ called") self.name = name # 设置实例属性 self.age = age # 使用 p = Person("Alice", 30) # 输出:__init__ called print(p.name) # Alice
关键点:
每个类可以定义自己的
__init__
如果未定义,继承父类的
__init__
可以调用父类的
__init__
:super().__init__(args)
不是构造函数(实际创建对象的是
__new__
)
2.__new__方法:对象创建器
作用:实际创建类的新实例
调用时机:在
__init__
之前自动调用参数:第一个参数必须是
cls
(指向当前类)返回值:必须返回创建好的实例对象
核心职责:
控制实例创建过程
决定是否返回新实例或已有实例
可以返回其他类的实例
class Singleton: _instance = None def __new__(cls, *args, **kwargs): print("__new__ called") if not cls._instance: # 创建新实例(调用父类的__new__) cls._instance = super().__new__(cls) return cls._instance # 返回实例(新或已有) def __init__(self, value): print("__init__ called") self.value = value # 使用 s1 = Singleton(10) # 输出: __new__ called -> __init__ called s2 = Singleton(20) # 输出: __new__ called -> __init__ called print(s1 is s2) # True(相同实例) print(s1.value) # 20(注意:__init__被再次调用!)
关键点:
必须返回有效的对象实例
如果返回非当前类实例,
__init__
不会被调用常用场景:单例模式、不可变类型子类化
元类中
__new__
创建的是类对象本身
3.__call__方法:对象调用器
作用:使类的实例可以像函数一样被调用
调用时机:当实例后加
()
时自动调用参数:第一个参数必须是
self
(指向实例)返回值:任意类型值
核心职责:
定义实例作为函数的行为
实现装饰器类
创建有状态的函数对象
class Adder: def __init__(self, base): self.base = base def __call__(self, x): print("__call__ invoked") return self.base + x # 使用 add5 = Adder(5) # 创建可调用对象 print(add5(3)) # 输出: __call__ invoked -> 8 print(add5(10)) # 输出: __call__ invoked -> 15
高级应用:装饰器类
class TraceCalls: def __init__(self, func): self.func = func 编程客栈 self.call_count = 0 def __call__(self, *args, **kwargs): self.call_count += 1 print(f"Call #{self.call_count} to {self.func.__name__}") return self.func(*args, **kwargs) @TraceCalls def multiply(a, b): return a * b print(multiply(3, 4)) # 输出: # Call #1 to multiply # 12 print(multiply(5, 6)) # 输出: # Call #2 to multiply # 30
三者的协作流程
class Example: def __new__(clsjavascript, *args, **kwargs): print("1. __new__: Creating instance") instance = super().__new__(cls) return instance def __init__(self, value): print("2. __init__: Initializing instance") self.value = value def __call__(self, multiplier): print("3. __call__: Invoking instance") return self.value * multiplier # 完整生命周期 e = Example(10) # 输出: # 1. __new__: Creating instance # 2. __init__: Initializing instance result = e(5) # 输出: # 3. __call__: Invoking instance print(result) # 50
关键对比表
特性 | __new__ | __init__ | __call__ |
---|---|---|---|
角色 | 对象创建器 | 对象初始化器 | 对象调用器 |
调用时机 | 创建实例时(最先) | __new__ 之后 | 实例被调用时 |
首参数 | cls (类引用) | self (实例引用) | self (实例引用) |
返回值 | 必须返回实例对象 | 必须返回 None | 可返回任意值 |
主要用途 | 控制实例创建过程 | 初始化实例属性 | 使实例可像函数一样调用 |
是否必需 | 不定义则用 object.__new__ | 不定义则跳过初始化 | 不定义则实例不可调用 |
典型场景 | 单例模式、不可变类型 | 常规对象初始化 | 装饰器类、函数对象 |
高级应用场景
1. 不可变类型扩展
cl编程客栈ass UppercaseStr(str): def __new__(cls, value): # 在创建前修改值 return super().__new__(cls, value.upper()) s = UppercaseStr("hello") print(s) # "HELLO"(不可变对象在创建时确定值)
2. 对象工厂
编程class Animal: def __new__(cls, animal_type, *args): if animal_type == "dog": return Dog(*args) elif animal_phptype == "cat": return Cat(*args) raise ValueError(f"Unknown animal: {animal_type}") class Dog: def __init__(self, name): self.name = name class Cat: def __init__(self, name): self.name = name d = Animal("dog", "Buddy") print(type(d), d.name) # <class '__main__.Dog'> Buddy
3. 带状态的装饰器
class Retry: def __init__(self, max_attempts=3): self.max_attempts = max_attempts def __call__(self, func): def wrapper(*args, **kwargs): for attempt in range(1, self.max_attempts+1): try: return func(*args, **kwargs) except Exception as e: print(f"Attempt {attempt} failed: {e}") raise RuntimeError("All attempts failed") return wrapper @Retry(max_attempts=2) def risky_operation(): import random if random.random() < 0.7: raise ValueError("Random failure") return "Success" print(risky_operation())
常见陷阱与解决方案
1. __init__ 中忘记返回 None
class Mistake: def __init__(self): return 42 # TypeError: __init__() should return None
2.__new__ 忘记返回实例
class BadClass: def __new__(cls): print("Forgot to return instance") # 返回None -> TypeError
3.单例模式中的重复初始化
解决方案:使用标志位控制
class SafeSingleton: _instance = None _initialized = False def __new__(cls): if not cls._instance: cls._instance = super().__new__(cls) return cls._instance def __init__(self): if not self.__class__._initialized: # 初始化代码 self.__class__._initialized = True
4.__call__ 与 __init__ 参数混淆
掌握这三个特殊方法的区别和协作机制,能够让你更精细地控制 Python 对象的整个生命周期,实现更高级的设计模式。
总结
到此这篇关于Python中的 __init__、__new__ 和 __call__的文章就介绍到这了,更多相关Python __init__、__new__ 和 __call__内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论