Python中的 __init__、__new__ 和 __call__示例详解

 更新时间:2025年09月01日 10:26:58   作者:哈拉索zbc  
这篇文章主要介绍了Python中__init__、__new__ 和 __call__的相关资料,它们分别负责对象创建、初始化和调用,用于实现单例模式、装饰器等高级功能,需要的朋友可以参考下

这三个特殊方法是 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__(cls, *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. 不可变类型扩展

class 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_type == "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__内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Django+python服务器部署与环境部署教程详解

    Django+python服务器部署与环境部署教程详解

    这篇文章主要介绍了Django+python服务器部署与环境部署教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • cProfile Python性能分析工具使用详解

    cProfile Python性能分析工具使用详解

    这篇文章主要介绍了cProfile Python性能分析工具使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • python实现数据预处理之填充缺失值的示例

    python实现数据预处理之填充缺失值的示例

    下面小编就为大家分享一篇python实现数据预处理之填充缺失值的示例。具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • python实现无边框进度条的实例代码

    python实现无边框进度条的实例代码

    这篇文章主要介绍了python实现无边框进度条的实例代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • 详解如何使用OpenCV和像素处理图像灰度化

    详解如何使用OpenCV和像素处理图像灰度化

    这篇文章主要为大家介绍了如何使用OpenCV和像素处理图像灰度化的方法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • 详谈在flask中使用jsonify和json.dumps的区别

    详谈在flask中使用jsonify和json.dumps的区别

    下面小编就为大家分享一篇详谈在flask中使用jsonify和json.dumps的区别,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • Django 自定义分页器的实现代码

    Django 自定义分页器的实现代码

    这篇文章主要介绍了Django 自定义分页器的实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • Django入门使用示例

    Django入门使用示例

    这篇文章主要介绍了Django入门使用示例,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • Python对list列表进行去重的几种方法

    Python对list列表进行去重的几种方法

    python 列表就是我们js中的数组了,我们下文整理几个常用的python 列表去重实现方法,非常的简单好用,通过代码示例讲解的非常详细,具有一定的参考价值,需要的朋友可以参考下
    2024-10-10
  • 解决tensorflow训练时内存持续增加并占满的问题

    解决tensorflow训练时内存持续增加并占满的问题

    今天小编就为大家分享一篇解决tensorflow训练时内存持续增加并占满的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-01-01

最新评论