单例

new实现单例

new至少要有一个参数cls,代表要实例化的类,new方法负责创建一个实例对象,在对象被创建的时候调用该方法它是一个类方法,new方法负责创建一个实例对象,在对象被创建的时候调用该方法它是一个类方法。new方法在返回一个实例之后,会自动的调用init方法,对实例进行初始化。如果new方法不返回值,或者返回的不是实例,那么它就不会自动的去调用init方法。此参数在实例化时由Python解释器自动提供

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        print cls,'xxxx'
        if not hasattr(cls,"_instance"):
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        
        return cls._instance

元类实现单例

class Singleton(type):
    def __init__(self, *args, **kwargs):
        print "__init__"
        self.__instance = None
        super(Singleton,self).__init__(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        print "__call__"
        if self.__instance is None:
            self.__instance = super(Singleton,self).__call__(*args, **kwargs)
        return self.__instance


class Foo(object):
    __metaclass__ = Singleton #在代码执行到这里的时候,元类中的__new__方法和__init__方法其实已经被执行了,而不是在Foo实例化的时候执行。且仅会执行一次。只有再需要对原类做变动时才需要写new方法

为了更好理解上面单例,注意下面两种写法

class UpperAttrMetaClass(type):
    
    def __new__(upperattr_metaclass, future_class_name, future_class_parents, future_class_attr):
        print 'xxxxxxx'
        uppercase_attr = {}
        for name, value in future_class_attr.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = value
            else:
                uppercase_attr[name] = value
        return type.__new__(upperattr_metaclass,future_class_name, future_class_parents, uppercase_attr)#返回一个对象,但同时这个对象是一个类
    
    def __init__(upperattr_metaclass,*args, **kwargs):
        print 'init'
        upperattr_metaclass.__instance = None
        super(UpperAttrMetaClass,upperattr_metaclass).__init__(*args, **kwargs)
    def myprint(self, param):
        print param,'xxxxx'

    def __call__(upperattr_metaclass,*args, **kwargs):
        print 'call'
    #  return upperattr_metaclass
        if upperattr_metaclass.__instance is None:
            upperattr_metaclass.__instance = super(UpperAttrMetaClass,upperattr_metaclass ).__call__(*args, **kwargs)
        return upperattr_metaclass.__instance

下面两种写法 ,

class Test(object):
    __metaclass__ = UpperAttrMetaClass
    def __call__(self):
        print 'test call'
    def __new__(cls, *args, **kwargs):
        print 'test new'
        return super(Test, cls).__new__(cls,*args, **kwargs)
    def __init__(self):
        print 'test init'
    def myprint(self, param):
        print param
    aaaa = 22222
class Test(object):
    def __call__(self):
        print 'test call'
    def myprint(self, param):
        print param
    aaaa = 22222

Test = UpperAttrMetaClass('Test', (object,), {'myprint':Test().myprint, '__call__':Test().__call__, 'aaaa':Test().aaaa}) 

这里我们重写了call方法,一开始不理解

super(UpperAttrMetaClass,upperattr_metaclass ).__call__(*args, **kwargs)

为什么能得到实例,如果我们不重写call方法,Test()将得到实例对象,那么重写的话,重写的格式就是这样,在Test类中重写new,init方法这时被调用。

t = Test()

t.MYPRINT('xxx')
t2 = Test()
print t 
print t2.AAAA
print Test()

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python爱好者

Java基础笔记03

16980
来自专栏java学习

Java基础第三天学习笔记

03.01_Java语言基础(逻辑运算符的基本用法)(掌握) * A:逻辑运算符有哪些 * &,|,^,! * &&,|| * B:案例演示 * 逻辑运算...

29670
来自专栏CodingToDie

Python学习(五):函数

第5 章 函数 Table of Contents 函数调用 数据类型转换 定义函数 空函数 返回多个值 tuple 函数调用 Python内置了很多有用的函数...

46550
来自专栏新智元

2018 年最常见的 Python 面试题 & 答案

https://data-flair.training/blogs/python-tutorial/

34340
来自专栏云瓣

JS中遍历语法的比较

for循环 JavaScript 提供多种遍历语法。最原始的写法就是for循环。 let arr = [1,2,3,4,5]; for (var index ...

42740
来自专栏Java编程

Java抽象类与接口的区别

很多常见的面试题都会出诸如抽象类和接口有什么区别,什么情况下会使用抽象类和什么情况你会使用接口这样的问题。本文我们将仔细讨论这些话题。

1.1K110
来自专栏LeetCode

LeetCode <dp>152&628 Maximum Product Subarray

Given an integer array nums, find the contiguous subarray within an array (conta...

14340
来自专栏海天一树

小朋友学C语言(23):二进制与十进制之间的转换

在学本节之前,请先复习 小朋友学C语言(17):二进制 一、二进制转换为十进制的C语言代码 #include <stdio.h> #include <strin...

36550
来自专栏日常分享

Java 将两个有序数组合成为一个有序数组

   (2)将 两个数组 对应索引下的元素进行比较,小的一方 放入最终数组中的当前索引下的位置,并使小的一方数组的索引+1;

39010
来自专栏Android干货园

Kotlin初级(4)- - - 字符串和字符.md

13620

扫码关注云+社区

领取腾讯云代金券