Python中如何像iOS开发一样将Model封装成单例使用?

null
Python中如何像iOS开发一样将Model封装成单例使用?

5 回复

单机就是个伪全局,可以使用 classmethed


在Python里搞单例模式,方法挺多的。iOS开发里那种shared静态实例的方式,在Python里也能实现,而且更简单。

最Pythonic的方式是用模块导入的特性。Python模块在导入时只会执行一次,天然就是单例。比如你有个UserModel类,可以这么写:

# model.py
class UserModel:
    def __init__(self):
        self.data = {}
        print("UserModel实例化")  # 只会打印一次
    
    def update_data(self, key, value):
        self.data[key] = value
    
    def get_data(self):
        return self.data.copy()

# 创建全局实例
shared = UserModel()

然后在其他地方导入这个shared实例:

from model import shared

# 第一次使用
shared.update_data('name', '张三')
print(shared.get_data())  # {'name': '张三'}

# 在其他模块中导入的也是同一个实例
from model import shared
print(shared.get_data())  # 还是{'name': '张三'}

如果你想要更像iOS的语法,可以用类属性加__new__方法:

class ConfigModel:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance.settings = {}
        return cls._instance
    
    @classmethod
    def shared(cls):
        return cls()

# 使用方式
config1 = ConfigModel.shared()
config1.settings['theme'] = 'dark'

config2 = ConfigModel.shared()
print(config2.settings)  # {'theme': 'dark'}
print(config1 is config2)  # True,是同一个实例

还有个更简单的方法是用装饰器:

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

@singleton
class AppState:
    def __init__(self):
        self.state = {}

# 使用
state1 = AppState()
state2 = AppState()
print(state1 is state2)  # True

模块导入的方式最简单实用,推荐用这个。

这个对于 Python 有省事简单方法,在 python 中把要单例的东西放到一个文件(模块)中,然后所有调用者都直接 import 就是天然单例了。
闲得没事可以用__new__方法,创建好类的全局实例。在实例化时都返回那个全局实例就可以了。

这个样子哇。那懂了。
get

import 是天然的单列

回到顶部