python面试题-2018.1.30

问题:如何实现单例模式?

  1. 通过new方法来实现单例模式。
class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

变体:

class Singleton(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

  1. 通过装饰器来实现单例模式
from functools import wraps


def singleton(cls):
    instances = {}

    @wraps(cls)
    def wrapper(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]

    return wrapper

  1. 通过元类来创建单例模式,因为元类是用于创建类对象的类,类对象创建实例对象时一定会调用call方法,因此在调用call时候保证始终只创建一个实例即可。
class Singleton(type):
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
            return cls._instance


class Foo(object):
    __metaclass__ = Singleton

  1. 通过共享属性来实现单例模式(通过这种方式实现,只是两个对象有相同的属性,但是在实例化之后,one is two 将会返回False), 将所有实例的dict指向同一个字典,这样实例就共享相同的方法和属性。对任何实例的名字属性的设置,无论是在init中修改还是直接修改,所有的实例都会受到影响。不过实例的id是不同的。要保证类实例能共享属性,但不和子类共享。
class Singleton(object):
    _state = {}

    def __new__(cls, *args, **kwargs):
        orig = super(Singleton, cls).__new__(cls, *args, **kwargs)
        orig.__dict__ = cls._state
        return orig

  1. 使用模块, Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:
# singleton.py
class Singleton(object):
    def foo(self):
        pass


my_singleton = Singleton()

变体:

# singleton.py
import sys


class Singleton(object):
    pass


sys.modules[__name__] = Singleton()

你可能感兴趣的:(python面试题-2018.1.30)