zoukankan      html  css  js  c++  java
  • python的__init__和__new__

    本文所有实例代码在python3.7下

    一.__new__和__init__区别

    1.__new__先于__init__执行;__new__是相当于其他OOP语言的构造方法,负责创建实例;之后,__init__负责初始化实例属性。__new__处理对象创建,__ init__处理对象初始化。

    2.__new__是一个特殊的静态方法(没有使用装饰器 @staticmethod);由python解释器调用,如果该类没有__new__,则调用父类的__new__.

    3.如果我们创建一个类的实例,代码如下:

    class Foo:
        def __new__(cls, *args, **kwargs):
            return super().__new__(cls)
    
        def __init__(self, x, y):
            self.__x = x
            self.__y = y
    
    foo = Foo(10, 20)
    

      

    __init__返回为None;
    __new__返回了一个创建的实例,其后作为__init__中的self传入

    4.通过__new__创建实例,通常是

    super().__new__(cls)
    

    # cls为当前要创建的类

    5.如果__new__返回它自己的类的实例,那么将使用实例作为第一个被调用的__init__方法的self参数,__init__将隐式调用。
    如果__new__方法返回除这个类之外的其他实例,则不会调用实例__init__方法。在这种情况下,您必须自己调用__init__方法。

    看一个返回类实例之外的例子:

    class Foo:
        def __init__(self, x):
            self.__x = x
    
        @property
        def x(self):
            return self.__x
    
    class Bar:
        def __new__(cls, *args, **kwargs):
            foo = super().__new__(Foo)
            foo.__init__(*args, **kwargs)
            return foo
    
    bar = Bar(10)
    print(bar.x)
    

      

    看一个返回自身类实例的:

    class Bar:
        def __new__(cls, *args, **kwargs):
            foo = super().__new__(cls)
            return foo
    
        def __init__(self, x):
            self.__x = x
    
        @property
        def x(self):
            return self.__x
    
    bar = Bar(10)
    print(bar.x)
    

      

    二.__new__的一些用途

    大多数情况下都不需要重写__new__。

    1.单例模式:

    class Foo:
        __instance = None
        def __new__(cls, *args, **kwargs):
            if not cls.__instance:
                cls.__instance = super().__new__(cls)
            return cls.__instance
    
    foo1 = Foo()
    foo2 = Foo()
    print(foo1, foo2)
    

      

    输出:
    <__main__.Foo object at 0x0000029A4B879048> <__main__.Foo object at 0x0000029A4B879048>
    可以看出foo1和foo2是同一个实例

    2.限制实例的创建数量:

    class Foo:
        __instance = []
        limit = 2
        def __new__(cls, *args, **kwargs):
            print(len(cls.__instance))
            if len(cls.__instance) == cls.limit:
                raise RuntimeError("Count not create instance. Limit %s reached" % cls.limit)
            instance = super().__new__(cls)
            cls.__instance.append(instance)
            return instance
    
        def __del__(self):
            self.__instance.remove(self)
    
    foo1 = Foo()
    foo2 = Foo()
    print(foo1, foo2)
    

      

    3.自定义实例创建

    您可以自定义创建的实例,并在调用初始化程序__init__之前对其进行一些操作。此外,您可以基于某些约束对实例创建施加限制

    def is_create():
        #根据条件判断是否可以创建
        return True
    
    class Foo:
        def __new__(cls, a, b):
            if not is_create():
                raise RuntimeError('实例不能被创建')
            instance = super().__new__(cls)
            instance.count = a + b
            return instance
    
        def __init__(self, a, b):
            pass
    
    foo = Foo(1, 2)
    print(foo.count)
    

      

    4.自定义返回的对象

    通常,当您实例化类时,它将返回该类的实例。您可以自定义此行为,并且可以返回所需的对象。

    class Foo:
        def __new__(cls, a, b):
            instance = super().__new__(cls)
            instance.__init__(a, b)
            return a + b
        def __init__(self, a, b):
            print('a+b')
    
    
    foo = Foo(1, 2)
    print(foo)
    

      

    如果我们不从__new__方法返回实例对象,则必须显式调用__init__。

  • 相关阅读:
    SAP 会计科目
    固定资产采购
    MIRO 注意点
    移动类型与会计科目的字段选择
    特征、分类的命名规则
    采购进项税、 含税价转不含税价
    换手率
    内盘、外盘
    SAP 文本增强
    Intellj IDEA 问题集锦
  • 原文地址:https://www.cnblogs.com/itfenqing/p/10225491.html
Copyright © 2011-2022 走看看