面向对象补充-init和new方法及单例模式

init 和 new

  • __init__其实不是实例化对象后第一个调用的方法,最先调用的方法其实是__new__方法。
  • new方法作用:a.在内存中为对象分配空间 ;b.返回对象的引用
  • 一个对象的实例化的过程是先执行new方法, 如果没有重写new方法,默认调用object里面的new方法,python解释器首先会调用new方法为对象分配空间,返回一个实例对象,传递给init方法,然后再调用init方法,对这个对象进行初始化
class Human(object):
    def __init__(self, name):
        self.name = name  # 实例属性
        print('这是init中的self:', self)
        print('名字是:', self.name)


    def __new__(cls, *args, **kwargs):
        print('这是new中的cls:', cls)
        print('这是new方法')
        print('这是new方法中需要返回的值:', object.__new__(cls))
        return object.__new__(cls)  # 返回对象引用

print('这是类:', Human) # 这是类: <class '__main__.Human'>
hu = Human('LIULIU')
# 这是new中的cls: <class '__main__.Human'>
# 这是new方法
# 这是new方法中需要返回的值: <__main__.Human object at 0x0000018BB396A3D0>
# 这是init中的self: <__main__.Human object at 0x0000018BB396A3D0>
# 名字是: LIULIU
print('这是第一次实例化的对象:', hu) # 这是第一次实例化的对象: <__main__.Human object at 0x0000018BB396A3D0>

# 总结:
# 1.init方法是什么时候被自动调用?         实例化的时候调用
# 2.new方法是用来创建实例对象,new方法是从哪里来的?     object
# 3.self 里面是什么?    self代表实例对象本身; 他是new方法创建的,然后发送给init方法去使用

# 4.init和new的区别
# new方法:创建对象;  init方法:初始化对象
# new:返回对象引用    init:定义实例属性
# new:是类级别的方法   init:是实例级别的方法

单例模式

  • 单例模式是一个特殊的类,这个类只能创建一次实例
  • 单例模式下可以节省内存空间,实例化不同对象会产生不同的内容地址,造成资源浪费
  • 实现单例模式的方法:
    • 1.通过@classmethod
    • 2.通过装饰器实现
    • 3.通过__new__实现 (重点)
    • 4.通过导入模块时实现
# 单例设计流程
# 1. 定义一个类属性,初始值是None, 用于记录单例对象的引用
# 2.重写new方法
# 3.进行判断, 如果类属性是None, 把new方法返回的对象引用保存进去
# 4.返回类属性中记录的对象引用

# 通过new来实现单例模式

class Eaxm(object):
    # 记录第一个被创建的对象引用
    ins = None  # 类属性

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

    def __new__(cls, *args, **kwargs):
        # 1.判断类属性是否为空
        if cls.ins == None:
            # 2.调用父类的new方法,为第一个对象分配空间
            cls.ins = object.__new__(cls)
        # 3.返回类属性保持的对象引用
        return cls.ins

# 单例模式:每一次实例化所创建的实例都是同一个,内存地址都一样
a1 = Eaxm()
print(a1)
a2 = Eaxm()
print(a2)
a3 = Eaxm()
print(a3)
# init方法
# <__main__.Eaxm object at 0x000001F7AE25A460>
# init方法
# <__main__.Eaxm object at 0x000001F7AE25A460>
# init方法
# <__main__.Eaxm object at 0x000001F7AE25A460>

# 通过装饰器来实现

def outer(fn):  # fn是被修饰的类名 -- Test
    # 创建一个字典来保存类的实例对象
    ins = {}
    def inner():
        # 先判断这个类有没有对象
        if fn not in ins:
            # 创建一个对象,保存在字典中
            ins[fn] = fn()   # fn是类名, 在ins中是键;  fn()是实例化的对象, 在ins中是值
            print('inner函数中fn', fn)    # <class '__main__.Test'>
            print('inner函数中ins', ins)  # {<class '__main__.Test'>: <__main__.Test object at 0x000001D6AFACCC48>}
            print('inner函数中ins[fn]', ins[fn])  # <__main__.Test object at 0x000001D6AFACCC48>

        # 将实例对象返回
        return ins[fn]  # <__main__.Test object at 0x000001F45DCC4670>
    return inner  # <__main__.Test object at 0x000001F45DCC4670>
@outer  # 装饰器修饰的是Test类
class Test(object):
    pass

te = Test()
print(te)
te2 = Test()
print(te2)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值