开发者

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)!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜