Python中的__new__和__init__函数理解

本文深入解析Python类构造机制,重点介绍__new__和__init__方法的区别与应用场景,包括单例模式实现、属性规范化及类属性修改等高级技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先看如下代码:

class  User:

    def __new__(cls):

        print("new")

        a = super().__new__(cls)

        print(a)

        print(cls.__bases__)

        return a

    def __init__(self):

        print("init")

        print(self)

 

a = User()

输出:

new
<__main__.User object at 0x0000000003E072B0>
(<class 'object'>,)
init
<__main__.User object at 0x0000000003E072B0>

说明在定义一个对象时, __new__在__init__之前被调用,且__new__返回的cls即为__init__的self,__init__不需要返回值

返回super().__new__(cls)(或者object.__new__(cls))的作用是什么呢?User的父类是object,User调用父类的__new__是为了继承父类的方法和属性,什么情况下使用 __new__() 呢?答案很简单,在 __init__() 不够用的时候。

比如,在定义元类的时候,

比如,在需要对属性的名称进行规范化的时候(属性名可以作为__new__函数的参数进行操作),

比如,要修改固定类的属性时(比如,修改int总为正整数,str总为大写,定义单例模式)等等。

1、__new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供

2、__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例。若__new__()没有正确返回当前类cls的实例,那__init__()将不会被调用,即使是父类的实例也不行。

__init__用法:

class Bird:

    def __init__(self):

          self.hungry = True

    def eat(self):

          if self.hungry:

               print('Ahahahah')

          else:

               print('No thanks!')

class SongBird(Bird):

     def __init__(self):

          self.sound = 'Squawk'

          super(SongBird,self).__init__()

          #super().__new__(self)

     def sing(self):

          print("self.sing()")

sb = SongBird()

sb.sing()    # 能正常输出

sb.eat()  

输出:

self.sing()
Ahahahah

当子类定义了__init__函数时,必须显式的执行super(子类名,self).__init__()(或者super().__init__()),用来继承父类的属性,否则父类属性将不会被继承

__new__应用于单例模式

什么是单例模式,顾名思义,系统中只能存在一个类的一个实例,所有对实例的属性的操作都是全局的。看代码:

class A:

    __isinstance = False  # 设置一个私有变量,默认没有被实例化

    def __init__(self, name):

        self.name = name #name属性

    def __new__(cls, *args, **kwargs):

        if cls.__isinstance:  

            return cls.__isinstance  # 返回实例化对象

        cls.__isinstance = object.__new__(cls)  # 否则实例化

        return cls.__isinstance  # 返回实例化的对象

# 实例化三个对象

a = A('张三')

b = A('李四')

c = A('王五')

# 打印三个对象的地址,结果都是一个地址

print(a)  

print(b)  

print(c)  

print(a.name)

print(b.name)

print(c.name)

a.name='xxxx'

print(c.name)

输出

<__main__.A object at 0x0000000002354978>
<__main__.A object at 0x0000000002354978>
<__main__.A object at 0x0000000002354978>
王五
王五
王五
xxxx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值