首页 > 编程语言 >Python常见面试题007. 谈谈Python中__init__和__new__的区别

Python常见面试题007. 谈谈Python中__init__和__new__的区别

时间:2023-03-07 22:12:39浏览次数:45  
标签:__ 面试题 Python instance init new class cls

007. 谈谈Python中__init__和__new__的区别

  • python中关于dunder method双下方法,或magic method魔术方法的描述多在

    https://docs.python.org/zh-cn/3.9/reference/datamodel.html#special-method-names
    

实例演示特性

  1. __new__是个静态方法(要看源码了),__init__是实例方法

  2. __new__需要返回一个实例,如果不返回,新实例的__init__不会被执行

    class Person:
        def __new__(cls, *args, **kwargs):
            return 'new'
    
        def __init__(self):
            print('calling init')
    
    
    wuxianfeng = Person()  # 什么都不会打印,如果注释掉new方法就可以了
    
    
    #当然你也可以这样写
    class Person:
        def __new__(cls, *args, **kwargs):
            instance = super().__new__(cls, *args, **kwargs)
            return instance
    
        def __init__(self):
            print('calling init')
    
    
    wuxianfeng = Person() # 也是会打印的
    
    
  3. __init__只能返回None

    class Person:
        def __init__(self):
            print('calling init')
            return 1
    
    wuxianfeng = Person()
    # 报错 TypeError: __init__() should return None, not 'int'
    # 但是也会输出calling init
    
    
  4. __new__在__init__之前

    class Person:
        def __new__(cls, *args, **kwargs):
            print('calling new')
            instance = super().__new__(cls, *args, **kwargs)
            return instance
    
        def __init__(self):
            print('calling init')
    
    
    wuxianfeng = Person()  # 先打印 calling new 再打印 calling init
    
    
    wuxianfeng = Person()
    
    # 你可以理解为这样的一个过程(参考https://www.bilibili.com/video/BV1b84y1e7hG)
    
    wuxianfeng = __new__(Person)
    
    __init__(wuxianfeng )
    
    
  5. 如果我们在建立一个object的过程中,传入了一些参数,那么这些参数既会被传入到new里也会被传入到init里

    class Person:
        def __new__(cls, x):
            print(f'calling new,and {x}')
            instance = super().__new__(cls)
            return instance
    
        def __init__(self,x):
            self.x = x
            print(f'calling init,and get {self.x}')
    
    
    wuxianfeng = Person('wxf')
    # calling new,and wxf
    # calling init,and get wxf
    
    
    如果在上面的代码中你去掉__new__(cls, x):中的,x,IDE会给你提示:签名不兼容,而且是双向的,new提示不兼容init,init提示不兼容new
    
    
    
    

  • 说在最后
    • __init__是大家都必须要掌握的,也是用的最多的魔术方法了
    • __new__是从一个class建立一个object的过程,如果你要更改这个过程(比如单例中,你在建立object之前要判断是否有建立过obj,从而确定自己是否要再建立),你就可以考虑用__new__
    • __init__是有了上面的__new__出来的object后对它进行初始化的一个过程
    • metaclass里面对new是用的相对多一些

官方说明

  • __new__中文部分

    object.__new__(cls[, ...])
    调用以创建一个 cls 类的新实例。__new__() 是一个静态方法 (因为是特例所以你不需要显式地声明),它会将所请求实例所属的类作为第一个参数。其余的参数会被传递给对象构造器表达式 (对类的调用)。__new__() 的返回值应为新对象实例 (通常是 cls 的实例)。
    
    典型的实现会附带适宜的参数使用 super().__new__(cls[, ...]),通过超类的 __new__() 方法来创建一个类的新实例,然后根据需要修改新创建的实例再将其返回。
    
    如果 __new__() 在构造对象期间被发起调用并且它返回了一个 cls 的实例,则新实例的 __init__() 方法将以 __init__(self[, ...]) 的形式被发起调用,其中 self 为新实例而其余的参数与被传给对象构造器的参数相同。
    
    如果 __new__() 未返回一个 cls 的实例,则新实例的 __init__() 方法就不会被执行。
    
    __new__() 的目的主要是允许不可变类型的子类 (例如 int, str 或 tuple) 定制实例创建过程。它也常会在自定义元类中被重载以便定制类创建过程。
    
  • __new__英文部分

    object.__new__(cls[, ...])
    Called to create a new instance of class cls. __new__() is a static method (special-cased so you need not declare it as such) that takes the class of which an instance was requested as its first argument. The remaining arguments are those passed to the object constructor expression (the call to the class). The return value of __new__() should be the new object instance (usually an instance of cls).
    
    Typical implementations create a new instance of the class by invoking the superclass’s __new__() method using super().__new__(cls[, ...]) with appropriate arguments and then modifying the newly-created instance as necessary before returning it.
    
    If __new__() is invoked during object construction and it returns an instance of cls, then the new instance’s __init__() method will be invoked like __init__(self[, ...]), where self is the new instance and the remaining arguments are the same as were passed to the object constructor.
    
    If __new__() does not return an instance of cls, then the new instance’s __init__() method will not be invoked.
    
    __new__() is intended mainly to allow subclasses of immutable types (like int, str, or tuple) to customize instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.
    
  • __init__中文部分

    在实例 (通过 __new__()) 被创建之后,返回调用者之前调用。其参数与传递给类构造器表达式的参数相同。一个基类如果有 __init__() 方法,则其所派生的类如果也有 __init__() 方法,就必须显式地调用它以确保实例基类部分的正确初始化;例如: super().__init__([args...]).
    
    因为对象是由 __new__() 和 __init__() 协作构造完成的 (由 __new__() 创建,并由 __init__() 定制),所以 __init__() 返回的值只能是 None,否则会在运行时引发 TypeError。
    
  • __init__英文部分

    object.__init__(self[, ...])
    Called after the instance has been created (by __new__()), but before it is returned to the caller. The arguments are those passed to the class constructor expression. If a base class has an __init__() method, the derived class’s __init__() method, if any, must explicitly call it to ensure proper initialization of the base class part of the instance; for example: super().__init__([args...]).
    
    Because __new__() and __init__() work together in constructing objects (__new__() to create it, and __init__() to customize it), no non-None value may be returned by __init__(); doing so will cause a TypeError to be raised at runtime.
    

标签:__,面试题,Python,instance,init,new,class,cls
From: https://www.cnblogs.com/wuxianfeng023/p/17188362.html

相关文章

  • PAT Basic 1013. 数素数
    PATBasic1013.数素数1.题目描述:令 \(P_i\) 表示第 \(i\) 个素数。现任给两个正整数 \(M≤N≤10^4\),请输出 \(P_M\) 到 \(P_N\) 的所有素数。2.输入格式:......
  • 《陀螺的进动动力是重力作用。 地轴进动的力怎么不是重力呢?》 回复
    《陀螺的进动动力是重力作用。地轴进动的力怎么不是重力呢?》      https://tieba.baidu.com/p/8297918012     。  回复 3楼   @黎合胜......
  • 进程和线程、协程的区别
    1.进程进程是程序一次动态执行的过程,是程序运行的基本单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。进程占据独立的内存,所以上下文进程间的切......
  • Java语言概述
    吾心安处即吾乡。吾乡何处不可眠1.Java概述是SUN(StanfordUniversityNetwork,斯坦福大学网络公司)1995年推出的一门高级编程语言。是一种面向Internet的编程......
  • ITLES Test Planning
     LeadingVideos:导引VocabularybuildingOther:538考点词 提取码:q44z Speaking???ListeningOther:王陆语料库 提......
  • 外观模式
    概述设计模式一书中对于“外观模式”的意图描述如下:为子系统中的u一组接口提供一个一致的界面,外观模式定义了一个高层的接口,这个接口使得这一子系统更加容易使用具......
  • Ubuntu服务器ssh缓慢问题解决
    Ubuntu服务器ssh缓慢问题解决现象:ssh登陆或su-账号时间较长 排查:1、查看了/var/log/syslog未发现明显报错2、查看/var/log/auth.log发现有pam_systemd:Failedtocreate......
  • 2023爬虫学习笔记 -- m3u8视频下载
    一、目标地址https://www.XXXX.com/二、获取mu38文件1、点击XHR,刷新页面,会看到这里有两个m3u8文件2、将m3u8地址复制到浏览器,会自动下载下来,index内容如下mixed内容如下3、......
  • Spring启用Log4日志框架
    配置maven依赖<!--log4j2的依赖--><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId>......
  • CCF 2014-3
    一:试题编号:2014-3-1试题名称:​相反数时间限制:1.0s内存限制:256.0MB问题描述:问题描述有N个非零且各不相同的整数。请你编一个程序求出它们中有多少对相反数(a和-a为一对......