• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    Python中的魔术方法__new__详解

    发布者: 涵韵 | 发布时间: 2025-6-17 08:05| 查看数: 90| 评论数: 0|帖子模式

    一、核心意义与机制


    1.1 构造过程原理



    1.2 与 __init__ 对比

    特性__new____init__方法类型静态方法实例方法返回值必须返回实例对象无返回值调用时机创建实例时首先调用在 __new__ 之后调用主要职责控制实例创建过程初始化实例属性
    二、核心功能解析


    2.1 核心能力


    • 控制实例创建过程
    • 决定是否生成新实例
    • 修改实例创建逻辑
    • 实现设计模式底层支持

    2.2 方法签名

    元类中的
    1. __new__
    复制代码
    参数(示例 4.1)

    • 样例
    1. class Meta(type):
    2.     def __new__(mcs, name, bases, attrs):
    3.         # 参数列表固定
    4.         return super().__new__(mcs, name, bases, attrs)
    复制代码

    • 参数解析表
    参数名类型说明mcstype元类自身(约定命名,类似 cls 代表类)namestr要创建的类名(如 "MyClass")basestuple基类列表(继承的父类)attrsdict类属性字典(包含方法、类变量等)调用逻辑

    • 元类用于​​创建类对象​​(不是实例对象)
    • 参数由解释器在定义类时自动传入
      1. super().__new__
      复制代码
      最终调用
      1. type.__new__
      复制代码
      生成类对象
    不可变类型子类的
    1. __new__
    复制代码
    (示例 3.2)
    样例
    1. class ImmutableStr(str):
    2.     def __new__(cls, value):
    3.         return super().__new__(cls, processed_value)
    复制代码

    • 参数解析表
    参数名类型说明clstype当前类对象(ImmutableStr)valueAny用户自定义参数(初始化输入值)调用逻辑

    • 继承自不可变类型(
      1. str/int/tuple
      复制代码
      等)
    • 必须通过
      1. __new__
      复制代码
      完成实例创建
      1. super().__new__
      复制代码
      调用父类(
      1. str
      复制代码
      )的构造方法
    • 参数需匹配父类
      1. __new__
      复制代码
      的要求(如
      1. str
      复制代码
      需要传入初始化字符串)
    可变类型普通类的
    1. __new__
    复制代码
    (示例 3.1)
    样例
    1. class Singleton:
    2.     def __new__(cls, *args, ​**​kwargs):
    3.         return super().__new__(cls)
    复制代码

    • 参数解析表
    参数名类型说明cls`当前类对象(Singleton)*argstuple位置参数(与 __init__ 共享参数)​**​kwargsdict关键字参数(与 __init__ 共享参数)调用逻辑

    • 普通类的实例创建流程
      1. super().__new__
      复制代码
      调用
      1. object.__new__
      复制代码
      生成实例
    • 参数需与
      1. __init__
      复制代码
      方法兼容

    2.3 参数传递关系图示



    2.4 核心记忆要点

    ​​元类
    1. __new__
    复制代码
    的四个参数是固定结构​​

    • 用于构建类对象(类的模板)
    • 参数由解释器自动填充
    ​​普通类
    1. __new__
    复制代码
    第一个参数必为
    1. cls​​
    复制代码

    • 后续参数需与
      1. __init__
      复制代码
      匹配
    • 不可变类型需要完全重写参数列表
    1. ​​super().__new__
    复制代码
    的参数必须与父类一致​​

    • 元类中:
      1. super().__new__(mcs, name, bases, attrs)
      复制代码
    • 普通类中:
      1. super().__new__(cls[, ...])
      复制代码

    三、典型应用场景


    3.1 单例模式实现
    1. class Singleton:
    2.     _instance = None
    3.    
    4.     def __new__(cls, *args, ​**​kwargs):
    5.         if not cls._instance:
    6.             cls._instance = super().__new__(cls)
    7.         return cls._instance

    8. a = Singleton()
    9. b = Singleton()
    10. print(a is b)  # True
    复制代码
    3.2 不可变类型扩展
    1. class ImmutableStr(str):
    2.     def __new__(cls, value):
    3.         # 预处理字符串
    4.         processed = value.strip().upper()
    5.         return super().__new__(cls, processed)
    6.    
    7. s = ImmutableStr("  hello  ")
    8. print(s)  # "HELLO"
    复制代码
    3.3 对象池技术
    1. class ConnectionPool:
    2.     _pool = []
    3.     _max_size = 5
    4.    
    5.     def __new__(cls):
    6.         if len(cls._pool) < cls._max_size:
    7.             obj = super().__new__(cls)
    8.             cls._pool.append(obj)
    9.             return obj
    10.         return cls._pool.pop(0)

    11. conn1 = ConnectionPool()
    12. conn2 = ConnectionPool()
    复制代码
    四、高级应用技巧


    4.1 元类协作
    1. class Meta(type):
    2.     def __new__(mcs, name, bases, attrs):
    3.         # 添加类属性
    4.         attrs['version'] = 1.0
    5.         return super().__new__(mcs, name, bases, attrs)

    6. class MyClass(metaclass=Meta):
    7.     pass

    8. print(MyClass.version)  # 1.0
    复制代码
    4.2 参数预处理
    1. class SmartTuple(tuple):
    2.     def __new__(cls, iterable):
    3.         # 过滤非数字元素
    4.         filtered = (x for x in iterable if isinstance(x, (int, float)))
    5.         return super().__new__(cls, filtered)
    6.    
    7. t = SmartTuple([1, 'a', 3.14, None])
    8. print(t)  # (1, 3.14)
    复制代码
    五、继承体系中的使用


    5.1 继承链处理
    1. class Base:
    2.     def __new__(cls, *args, ​**​kwargs):
    3.         print(f"Creating {cls.__name__}")
    4.         return super().__new__(cls)

    5. class Child(Base):
    6.     pass

    7. c = Child()  # 输出 "Creating Child"
    复制代码
    5.2 多继承处理
    1. class A:
    2.     def __new__(cls, *args, ​**​kwargs):
    3.         print("A's __new__")
    4.         return super().__new__(cls)

    5. class B:
    6.     def __new__(cls, *args, ​**​kwargs):
    7.         print("B's __new__")
    8.         return super().__new__(cls)

    9. class C(A, B):
    10.     def __new__(cls, *args, ​**​kwargs):
    11.         return A.__new__(cls)

    12. obj = C()  # 输出 "A's __new__"
    复制代码
    六、注意事项与调试


    6.1 常见错误
    1. class ErrorCase:
    2.     def __new__(cls):
    3.         # 错误:忘记返回实例
    4.         print("Creating instance")  # ❌ 无返回值
    5.         
    6.     def __init__(self):
    7.         print("Initializing")

    8. e = ErrorCase()  # TypeError
    复制代码
    6.2 调试技巧
    1. class DebugClass:
    2.     def __new__(cls, *args, ​**​kwargs):
    3.         print(f"__new__ args: {args}")
    4.         instance = super().__new__(cls)
    5.         print(f"Instance ID: {id(instance)}")
    6.         return instance
    7.    
    8.     def __init__(self, value):
    9.         print(f"__init__ value: {value}")

    10. d = DebugClass(42)
    复制代码
    七、性能优化建议


    7.1 对象缓存策略
    1. class ExpensiveObject:
    2.     _cache = {}
    3.    
    4.     def __new__(cls, config):
    5.         key = hash(frozenset(config.items()))
    6.         if key not in cls._cache:
    7.             instance = super().__new__(cls)
    8.             instance._init(config)
    9.             cls._cache[key] = instance
    10.         return cls._cache[key]
    11.    
    12.     def __init__(self, config):
    13.         # 避免重复初始化
    14.         self.config = config
    复制代码
    最佳实践总结​​


    • 优先使用
      1. super().__new__
      复制代码
      保证继承链正常
    • 修改不可变类型必须使用
      1. __new__
      复制代码
    • 单例模式要处理好线程安全问题
    • 避免在
      1. __new__
      复制代码
      中做耗时操作
    以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

    来源:https://www.jb51.net/python/339582h4x.htm
    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    ×

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表