zoukankan      html  css  js  c++  java
  • xadmin系列之单实例模式

    先看下单实例的定义

    python的模块实现单例模式是python语言特有的,python的模块天然就是单例的,因为python有个pyc文件,导入一次后,第二次导入直接从pyc中取数据了

    这里我们主要学习一下基于模块实现单例对象,这里利用的原理就是python的模块导入的特性,这个模块被第一次导入,会被执行一次,但是如果这个模块被再次导入,无论是在相同的文件还是在不同的文件中,第二次导入都不会再次执行

    如果要想通过模块导入实现单实例模式,则必须要在一个文件中定义一个类,这里要切记,在这个文件中一定要实例化这个类,然后在其他文件中导入这个实例对象,那么所有的文件中用的实例对象都是相同的一个

    比如我们看下下面的例子

    在mysingle.py文件中我们定义了一个类,且实例化了这个类

    class func(object):
        def foo(self):
            print("foo....")
    
    s1 = func()
    

      

    在main.py文件中导入两次mysingle.py文件的实例对象,这里因为导入的都是一个实例,当第一次导入的时候,mysingle.py文件就已经生成pyc文件,所以第二次导入不会在去实现mysingle.py这个文件,而是直接去pyc文件中获取实例变量,所以,我们这里打印实例对象的id,他们肯定是相同的

    from mysingle import s1
    
    
    from mysingle import s1 as new
    
    
    
    
    print(id(s1))
    print(id(new))
    

      

    结果两个实例对象的id值当然是相同的

    23991472
    23991472

    我们在看一个例子

    我们在func.py这个文件中也导入mysingle.py这个文件的实例对象,导入文件之后,我们定义了一个函数打印导入这个实例对象的内存第一,那么func.py中打印的内存地址和main.py中打印的内存地址也是一样的

    我们先看func.py这个文件

    from mysingle import s1
    
    def bar():
        print(id(s1))
    

      

    我们在main.py文件中导入上面的func.py文件,然后在main.py文件中执行bar函数

    from mysingle import s1
    
    
    from mysingle import s1 as new
    
    print(id(s1))
    print(id(new))
    
    from func import bar
    
    bar()
    

      

    这个时候我们打印了三个实例对象的内存地址,毫无疑问,他们的内存地址是相同的

    23991472
    23991472
    23991472

    我们看最后一个例子,前面的例子我们都是导入实例好的对象,这次我们导入mysingle.py中的类,然后在实例化这个类,我们得到的实例对象的内存地址是否相同呢,这个当然就不同了,因为每次实例化对象,都会重新开辟一个内存空间,我们前面的例子之所以不需要开辟新的内存空间,是因为我们导入的是一个实例对象

    下面的例子我们就是导入类,然后实例化,我们当然可以看到,两个对象的内存地址肯定是不一样的

    from mysingle import func
    
    f1 = func()
    
    f2 = func()
    

      

    结果当然是不一样的,因为他们是完全不同的两个实例对象

    23028752 23990736

    为了加深印象,我们在来看一个例子,完全是模仿django来写一个单实例的例子

     先看下site中的代码

    class Test(object):
        _register = {}
    
        def register(self,model):
            self._register[model] = model()
    
    
    test = Test()
    

      

    在看app1中的admin的代码

    from site import test
    
    class Cat(object):
        pass
    
    # c = Cat()
    test.register(Cat)
    
    print("------------>第一次",test._register)
    

      

    在看app2中的admin的代码

    from site import test
    
    class Dog(object):
        pass
    
    # d = Dog()
    test.register(Dog)
    
    print("------------>第二次",test._register)
    

      

    最后看下main文件的代码

    if __name__ == '__main__':
        from app1 import admin as admin1
        from app2 import admin as admin2
        from site import test
    
        print("------------>第三次",test._register)
    

      

    我们最后看下执行main的输出

     大家应该能明白了吧

     --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     单实例还是有其他的实现方式,这里就先不介绍了,因为我也不会,这里我们就先掌握基于模块导入实现单实例对象,这里要切记,在文件中定义一个类,然后必须要实例化这个类,同样,我们在其他位置导入的时候,则必须要导入实例对象,而不是类;实现的效果就是这个类只允许实例出来一个对象

    这里在补一个通过__new__方法实现单例模式的代码

    class Singloten(object):
        _instance = None
        def __new__(cls, *args, **kwargs):
            if not cls._instance:
                cls._instance = super(Singloten,cls).__new__(cls,*args,**kwargs)
            return cls._instance
    
    
    
    class myclass(Singloten):
        a = 1
    
    
    one = myclass()
    one.a = 5
    two = myclass()
    
    print(two.a)
    
    print(id(one),id(two))
    print(one == two)
    

      

    输出结果如下

  • 相关阅读:
    50个C/C++经典面试题
    多继承的构造顺序
    sizeof(struct)
    c++ 实现strcpy(),strlen()
    十天冲刺-01
    学习进度条(第八周)
    梦断代码阅读笔记01
    学习进度条(第七周)
    团队作业记账本开发NABCD
    学习进度条(第六周)
  • 原文地址:https://www.cnblogs.com/bainianminguo/p/9926412.html
Copyright © 2011-2022 走看看