zoukankan      html  css  js  c++  java
  • 单例模式

    ps:类只要加括号就会生成一个新的对象,无论参数是否相同,单例模式排除在外.

    class Demo:
        pass
    
    obj1 = Demo()
    obj2 = Demo()
    print(id(obj1))  # 1594519955888
    print(id(obj2))  # 1594519955832

     单例:

    多次调用类拿到的是同一个对象

    单例的实现:

    <1>基于classmethod

    class Mysql(object):
        _instance = None
        def __init__(self, host, port):
            self.host = host
            self.port = port
        @classmethod
        def singelton(cls):
            if not cls._instance:
                cls._instance = cls('127.0.0.1',8080)
    obj1 = Mysql.singelton()
    obj2 = Mysql.singelton()
    obj3 = Mysql('168.192.1.1',8088)
    print(id(obj1), id(obj2), id(obj3))  # 1731962064 1731962064 1736639656680

    <2>基于装饰器

    # 基于装饰器  本质:会将紧挨着它的变量名当做参数传入
    def singelton(cls):
        _instance = cls('127.0.0.1',8080)
        def inner(*args, **kwargs):
            if args or kwargs:
                obj = cls(*args, **kwargs)  # cls 是真正的 Mysql 类
                return obj
            return _instance
        return inner
    
    @singelton   # Mysql = singelton(Mysql)  函数加括号优先级最高,此时 Mysql就是inner
    class Mysql(object):
        def __init__(self, host, port):
            self.host = host
            self.port = port
    
    obj1 = Mysql()  # 其实是 inner()
    obj2 = Mysql()
    obj3 = Mysql('168.192.1.1',8088)
    print(id(obj1), id(obj2), id(obj3))  # 2661019235384 2661019235384 2661019235328

    <3>基于元类

    class MyClass(type):
        def __call__(self, *args, **kwargs):
            # 调用 Mysql 中的 _instance
            if not getattr(self,'_instance'):  # 此时的self是Mysql
                self._instance = super().__call__(*args, **kwargs)  # 调用父类的__call__产生对象赋值给 _instance 这个对象就是Mysql的对象
                # __call__固定会做三件事:
                # 1.产生空对象  __new__
                # 2.初始化对象  __init__
                # 3.返回该对象  return obj
            return self._instance
        pass
    
    class Mysql(object, metaclass=MyClass):  # 类加括号会走它元类中的__call__方法
        _instance = None
        def __init__(self, host, port):
            self.host = host
            self.port = port
    
    obj1 = Mysql('168.192.1.1',8088)
    obj2 = Mysql('168.192.1.1',9999)
    print(id(obj1), id(obj2))  # 2107832088112 2107832088112

    <4>基于__new__

    class Mysql(object):
        _instance = None
        def __init__(self, host, port):
            self.host = host
            self.port = port
        # __new__拦截类的创建过程,在类创建前先走__new__, 这里的__new__在Mysql实例化时触发
        def __new__(cls, *args, **kwargs):
            if not cls._instance:
                cls._instance = object.__new__(cls)  # 这里的cls每次都是最后实例化时那个Mysql
            return cls._instance
    
    obj1 = Mysql('168.192.1.1',8088)
    obj2 = Mysql('168.192.1.1',9999)
    print(id(obj1), id(obj2))  # 1512390747976  1512390747976

    <5>基于模块

    class Settings(object):pass
    
    settings = Settings()
    单例设计模式1.py
    from 单例设计模式1 import settings
    
    def func():
        print(id(settings))
    单例设计模式2.py
    # 1.
    from 单例设计模式1 import settings
    print(id(settings))  # 3078907535488
    from 单例设计模式1 import settings
    print(id(settings))  # 3078907535488
    # 模块导入一次后就不会在导入
    
    # 2.
    from 单例设计模式1 import settings
    from 单例设计模式2 import func
    
    print(id(settings))  # 2381785037456
    func()  # 2381785037456
    
    # 3.
    from 单例设计模式1 import settings,Settings
    print(id(settings))  # 2080793135592
    print(id(Settings()))  # 2080793135424
  • 相关阅读:
    linux--->curl
    linux--->定时任务
    php--->无限级分类
    php--->自己封装的简易版mvc框架
    php--->单例模式封装mysql操作类
    Linux使用退格键时出现^H ^?解决方法
    错误日志
    linux下redis服务器安装使用 安装php的redis扩展 安装laravel下的redis
    php system()
    laravel redis的使用
  • 原文地址:https://www.cnblogs.com/waller/p/11626670.html
Copyright © 2011-2022 走看看