Python 进阶 魔术方法 __new__

本贴最后更新于 393 天前,其中的信息可能已经物是人非

实践是检验真理的唯一标准:拷贝到pycharm一试便知

一、__new__的作用

俗话说:“没有对象? new一个。”

__new__创建对象的方法

__init__初始化对象

对象:new方法先创建,然后通过init方法初始化

注意点:一般情况不要重写new方法,除非有特定的需求需要使用new方法来实现
定义了new方法之后,需要调用父类的new来创建对象 并返回

什么情况下用:要干预类实例化对象的过程,
实例前后分别要做什么,通常装饰器也能实现,故通常不用__new__。


# 1、类中未创建__new__方法
class MyTestNoNew:  # Py3默认继承了object基类,== MyTestNoNew(object)
    def __init__(self):
        print('-------init------方法')


# 2、类中创建__new__方法,但里面没有创建对象,且没有返回对象
class MyTestNew(object):  # == MyTestHaveNewNoObj(object)
    def __init__(self):
        print('-------init------方法')

    def __new__(cls, *args, **kwargs):
        print('------new方法-------')


# 3、类中创建__new__方法,创建对象,但没有返回对象
class MyTestNewObj:

    def __init__(self):
        print('-------init------方法')

    def __new__(cls, *args, **kwargs):
        print('------new方法-------')
        obj = super().__new__(cls)


# 4、类中创建__new__方法,创建对象,有返回对象
class MyTestNewObjReturn:

    def __init__(self):
        print('-------init------方法')

    def __new__(cls, *args, **kwargs):
        print('------new方法-------')
        obj = super().__new__(cls)
        return obj


print('1、类中未创建__new__方法===============================================')
myTestNoNew = MyTestNoNew()
# -------init------方法
print('myTestNoNew:', myTestNoNew)
# myTestNoNew: <__main__.MyTestNoNew object at 0x000001508174A350>
# 因继承的object基类的__new__方法返回了对象,所以执行了初始化__init__方法。


print('2、类中创建__new__方法,但里面没创建对象,且没返回对象===============================================')
myTestNew = MyTestNew()
# ------new方法-------
print('myTestNew:', myTestNew)
# myTestNew: None
# 因自己创建的__new__方法没创建对象,所以没执行了初始化__init__方法。


print('3、类中创建__new__方法,创建对象,但没有返回对象===============================================')
myTestNewObj = MyTestNewObj()
# ------new方法-------
print('myTestNewObj:', myTestNewObj)
# myTestNewObj: None

# 因自己创建的__new__方法有创建,但没返回对象,所以没执行初始化__init__方法


print('4、类中创建__new__方法,创建对象,有返回对象===============================================')
myTestNewObjReturn = MyTestNewObjReturn()
# ------new方法-------
# -------init------方法
print('myTestNewObjReturn:', myTestNewObjReturn)
# myTestNewObjReturn: <__main__.MyTestNewObjReturn object at 0x00000181B81F4D90>
# 类中创建__new__方法,创建对象,且有返回对象,执行了初始化方法__init__

二、单例模式:通过__new__实现

1、非单例模式:通常同一个类每次实例化对象,都会创建不同的新对象。

2、单例模式:同一个类每次实例化对象,都是返回第一次创建的对象。
通过类的__new__方法实现

3、用私有属性:否则修改属性后不是单例模式。


# 1、非单例模式:通常同一个类每次实例化对象,都会创建不同的新对象
class MyClassNoNew:
    pass


# 2、单例模式:同一个类每次实例化对象,都是返回第一次创建的对象。
# 通过类的__new__方法实现
# 没用私有属性
class MyClassNew:
    # 不用私有属性,属性会被修改,非单例
    instance = False

    def __new__(cls, *args, **kwargs):
        # 判断类是否实例化过对象
        if cls.instance:
            # 如果有,则直接返回之前的对象
            return cls.instance
        else:
            # 如果没有则调用父类的方法,进行实例化,保存起来
            obj = super().__new__(cls)
            cls.instance = obj
            return cls.instance


# 2、单例模式:用私有属性
# 简化代码
class MyClassNewEasy:
    # 用私有属性:属性不会被修改
    __instance = None

    def __new__(cls, *args, **kwargs):
        # 判断类是否实例化过对象
        if not cls.__instance:
            # 如果没有则调用父类的方法,进行实例化,保存起来
            cls.__instance = super().__new__(cls)
        return cls.__instance


print('1、非单例模式:通常同一个类每次实例化对象,都会创建不同的新对象。===============================================')
myClassNoNew01 = MyClassNoNew()
myClassNoNew02 = MyClassNoNew()
myClassNoNew03 = MyClassNoNew()
print('myClassNoNew01:', myClassNoNew01)
print('myClassNoNew02:', myClassNoNew02)
print('myClassNoNew03:', myClassNoNew03)
# myClassNoNew01: <__main__.MyClassNoNew object at 0x0000016DE15194D0>
# myClassNoNew02: <__main__.MyClassNoNew object at 0x0000016DE1519510>
# myClassNoNew03: <__main__.MyClassNoNew object at 0x0000016DE1519550>


print('2、单例模式:没用私有属性。===============================================')
myClassNew01 = MyClassNew()
myClassNew02 = MyClassNew()
myClassNew03 = MyClassNew()
print('myClassNew01:', myClassNew01)
print('myClassNew02:', myClassNew02)
print('myClassNew03:', myClassNew03)
# myClassNew01: <__main__.MyClassNew object at 0x00000189CA049E90>
# myClassNew02: <__main__.MyClassNew object at 0x00000189CA049E90>
# myClassNew03: <__main__.MyClassNew object at 0x00000189CA049E90>

print('# 没用私有属性,可修改,非单例===============================================')
MyClassNew.instance = None
myClassNew04 = MyClassNew()
print('myClassNew04:', myClassNew04)
# myClassNew04: <__main__.MyClassNew object at 0x00000199B1369ED0>


print('# 单例模式:用私有属性 + 精简代码===============================================')
# 每次实例创建对象都相同,编号相同
myClassNewEasy01 = MyClassNewEasy()
myClassNewEasy02 = MyClassNewEasy()
myClassNewEasy03 = MyClassNewEasy()
print('myClassNewEasy01:', myClassNewEasy01)
print('myClassNewEasy02:', myClassNewEasy02)
print('myClassNewEasy03:', myClassNewEasy03)
# myClassNewEasy01: <__main__.MyClassNewEasy object at 0x000001DDFBDC9F10>
# myClassNewEasy02: <__main__.MyClassNewEasy object at 0x000001DDFBDC9F10>
# myClassNewEasy03: <__main__.MyClassNewEasy object at 0x000001DDFBDC9F10>

print('# 用私有属性,不可修改,仍单例===============================================')
MyClassNewEasy.__instance = None
myClassNewEasy04 = MyClassNewEasy()
print('myClassNewEasy04:', myClassNewEasy04)
# myClassNewEasy04: <__main__.MyClassNewEasy object at 0x000001DDFBDC9F10>

2 操作
qq5942527 在 2023-04-08 10:50:25 更新了该帖
qq5942527 在 2023-04-08 10:46:40 更新了该帖
回帖
请输入回帖内容 ...