taizilongxu / interview_python

关于Python的面试题
16.63k stars 5.55k forks source link

单例模式的问题 #24

Open zhjchina opened 8 years ago

zhjchina commented 8 years ago

单例模式第一种实现方法有bug,如下,A是一个单例类,B继承了A,当A实例化之后,再实例化B时,返回的是A的实例。 class A(Singleton): pass

class B(A): pass

a = A() b = B() print isinstance(b, B) False print isinstance(b, A) True

修改如下: class Singleton(object): _instance = {} def new(cls, _args, _kwargs): if cls in cls._instance: return cls._instance[cls] else: obj = super(Singleton, cls).new(cls, _args, _kwargs) cls._instance[cls] = obj return obj

lambdaplus commented 7 years ago

单例模式 例子2 共享属性 也有问题。

Python 3.6.0 |Anaconda 4.3.1 (64-bit)| (default, Dec 23 2016, 12:22:00) 
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: class Borg(object):
   ...:     _state = {}
   ...:     def __new__(cls, *args, **kw):
   ...:         ob = super(Borg, cls).__new__(cls, *args, **kw)
   ...:         ob.__dict__ = cls._state
   ...:         return ob
   ...: 
   ...: class MyClass2(Borg):
   ...:     a = 1
   ...:     

In [2]: a = MyClass2()

In [3]: b = MyClass2()

In [4]: id(a)
Out[4]: 140280935744904

In [6]: id(b)
Out[6]: 140280935776096

In [7]: c = Borg()

In [8]: d = Borg()

In [9]: id(c)
Out[9]: 140280935117376

In [10]: id(d)
Out[10]: 140280935073888
jackupdown commented 7 years ago

@baby5 根据前面的讲解,__instances = {}应该使用单下划线吧

jackupdown commented 7 years ago

@baby5 擦,貌似很有道理。 Special cases aren't special enough to break the rules. python之禅讲到,不要轻易打破规则。

MarcelArthur commented 7 years ago

单下划线命名的变量名是私有变量, 打破这个规则不合适吧(虽然不是严格的私有变量,仍然有办法访问到 逃

andersonshao commented 7 years ago
ob = super().__new__(cls)
z8seeker commented 6 years ago

单例模式中的装饰器版本有bug

当被装饰的类中 __init__() 方法有初始化参数时,将报 TypeError 异常。建议更改为:

def singleton(cls):
    instances = {}
    def getinstance(*args, **kw):
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]
    return getinstance