python 的单例模式

python设计模式中的 单例模式:单例模式可以通过__new__ 方法实现,而__new__ 方法一般用于继承不可变对象。

1、可变不可变对象

python中有可变对象和不可变对象两种。前者创建后,可改变,地址却不会改变,后者创建后都不能改变,一旦被改变了,就会产生一个新的对象。

class Mylist(object):

    def __init__(self,mylist_id,name=[ ]):

        self.mylist_id= mylist_id

        self.name= name

    def add_name(self,name):

        self.name.append(name)

mylist1= Mylist(1)

mylist1.add_name('zhangsan')

print(id(mylist1))

print(mylist1.name)

mylist2= Mylist(2)

mylist2.add_name('lisi')

print(id(mylist2))

print(mylist2.name)

print(id(mylist1.name))

print(id(mylist2.name))

结果图:


图1

有结果可知mylist1和mylist2的id号不一样,在不同地址,但是mylist2可以在1的基础上添加新的东西。这是因为 __init__函数在被创建的时候默认参数的值已经生成了往后继续用的时候在是前者的基础上,可以看到两个mylist.name的地址是一样的,所添加的名字在同一个地址里。

class Mylist(object):

    def __init__(self,mylist_id):

        self.mylist_id= mylist_id

        self.name= []

def add_name(self,name):

        self.name.append(name)

mylist1= Mylist(1)

mylist1.add_name('zhangsan')

print(id(mylist1))

print(mylist1.name)

mylist2= Mylist(2)

mylist2.add_name('lisi')

print(id(mylist2))

print(mylist2.name)

print(id(mylist1.name))

print(id(mylist2.name))

结果图:


图2

我们在__init__函数里面去掉name这个参数,self.name = [ ],相当于这个地方是空的,因为并没有传参。只有当调用add_name函数的时候在空列表里面添加名字,这时候不会因为创建__init__函数而产生默认缓存,导致每次在添加新内容都会在之前的缓存里面添加。这时两个mylist.name的地址也是不一样的。

2、__new__方法

这里涉及到一个__new__方法的使用,因为new方法正式用于继承一些不可变的class时,__new__函数是分配地址空间的,创建对象的第一步,而__init__是初始化对象的,属于第二步。__new__被定义为静态方法,需要传参数。需要返回值,返回的是实例化的实例,并且返回值是作为__init__的self参数传入__init__函数。

class Test(object):

    def __init__(self):

        print('__init__()')

def __new__(cls):

        print('__new__()')

        return object.__new__(cls)

if __name__== '__main__':

    test= Test()

结果图:

图3

由此可以看出,实例化类时,先调用的是__new__函数,然后才是__init__函数

3、通过__new_-方法实现单例模式

单例模式:常见的一种软件设计模式,主要目的是确保某一个类只有一个实例存在。

__new__方法可以用来实现设计模式中的单例模式,因为每次初始化实例对象的时候先调用的是__new__ 方法,我们需要对它重写保证实现这个类只有一个实例存在。

class Singleton(object):

    def __new__(cls):

        # 用 hasattr 判断类里是否有实例,如果没有继承之前的一个实例,如果没有返回一个实例。

        if not hasattr(cls,'instance'):

            cls.instance= object.__new__(cls)

return cls.instance

# def __init__(self):

#    pass

test1= Singleton()

test2= Singleton()

print(test1)

print(test2)

print (test1is test2)

结果图:

图4

通过__new__ 方法的重写,虽然实例化两次,但是是同一个地址里面,保证了只有一个实例

我们把__new__ 方法注释掉,直接用__init__方法:

class Singleton(object):

    # def __new__(cls):

    #    # 用 hasattr 判断类里是否有实例,如果没有继承之前的一个实例,如果没有返回一个实例。

    #    if not hasattr(cls, 'instance'):

#        cls.instance= object.__new__(cls)

#    return cls.instance

    def __init__(self):

pass

test1= Singleton()

test2= Singleton()

print(test1)

print(test2)

print (test1is test2)

结果图:


图5

没有使用__new__方法重写,直接用__init__时,就没办法保证有唯一的实例,实例化几次就会产生几个地址,并且不相同。

class Singleton(object):

    def __new__(cls):

        # 用 hasattr 判断类里是否有实例,如果没有继承之前的一个实例,如果没有返回一个实例。

        if not hasattr(cls,'instance'):

            cls.instance= object.__new__(cls)

return cls.instance

def __init__(self):

pass

    def action(self):

        return  id(self)

test1= Singleton()

test2= Singleton()

print(test1.action())

print(test2.action())



图6

再试一次,增加一个新的方法 action( ),用来返回地址。通过结果可以看到,实例化两次,action( )方法实现两次,输出两次结果,但两次输出的地址还是一样的。很明显如果注释掉__new__方法,那么地址是肯定不一样的。这里单例模式就起到作用了。避免了同一个内容被多次使用后,每次都要占用不同的地址,浪费了资源。

以上就是python的单例模式。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容