所谓的类属性方法是相对实例方法,也没有classmethod修饰,实例方法去掉self参数就是类属性方法,只能通过类调用,不能通过实例来调用,见下图。
下面简单介绍了通过类属性方法来实现单例模式。
初步实现:
class Singleton(object): instance = None def __init__(self): pass def get_instance(): if Singleton.instance is None: Singleton.instance = Singleton() return Singleton.instance a = Singleton.get_instance() b = Singleton.get_instance() print(id(a)) print(id(b))输出:
>>> 41281800 >>> 41281800
通过get_instance函数返回实例初步实现了效果,但是这个类似可以实例化,这就达不到单例的效果,见如下的代码:
class Singleton(object): instance = None def __init__(self): pass def get_instance(): if Singleton.instance is None: Singleton.instance = Singleton() return Singleton.instance a = Singleton.get_instance() b = Singleton.get_instance() c = Singleton() print(id(a)) print(id(b)) print(id(c))输出:
>>> 41281800 >>> 41281800 >>> 41281632c是通过类实例化的id和a、b的不一样。
有没有办法禁止通过类来实例化呢?我们可以在__init__中做文章,在__init__中抛出异常即可禁止实例化了,但是还是有问题,因为get_instance里面就是通过类来实例化的:
def get_instance(): if Singleton.instance is None: Singleton.instance = Singleton() return Singleton.instance
除了通过类来实例化就没有其他方法实例化了吗?有,我们可以通过父类object的__new__函数来实例化, get_instance函数修改为:
def get_instance(): if Singleton.instance is None: Singleton.instance = object.__new__(Singleton) return Singleton.instance
完整代码:
class Singleton(object): instance = None def __init__(self): raise SyntaxError('can not instance, please use get_instance') def get_instance(): if Singleton.instance is None: Singleton.instance = object.__new__(Singleton) return Singleton.instance a = Singleton.get_instance() b = Singleton.get_instance() print(id(a)) print(id(b)) c = Singleton() print(id(c))
输出:
>>> Traceback (most recent call last): File "E:/Code/python3/otherTest/classattrmethodSingleton.py", line 18, in <module> c = Singleton() File "E:/Code/python3/otherTest/classattrmethodSingleton.py", line 6, in __init__ raise SyntaxError('can not instance, please use get_instance') SyntaxError: can not instance, please use get_instance >>> 7333984 >>> 7333984
从完整代码和输出可以看出只能通过get_instance获取实例,不能通过类来实例化,通过类来实例化会报异常。