Skip to content
This repository has been archived by the owner on Mar 23, 2024. It is now read-only.

singleton 用这种方式实现python解释器可以查看内部实现 #14

Open
suterberg opened this issue Jan 3, 2024 · 1 comment

Comments

@suterberg
Copy link

suterberg commented Jan 3, 2024

import wrapt

INSTANCE = {}
ENABLED = True

@wrapt.decorator(enabled=ENABLED)
def singleton(wrapped, instance, args, kwargs):
global INSTANCE
if wrapped not in INSTANCE:
INSTANCE[wrapped] = wrapped(*args, **kwargs)
return INSTANCE[wrapped]

继承时使用 super().init()

@Sun-ZhenXing
Copy link

分享一下我常用的 @singleton 实现,推荐用元类实现能保持类的全部特性,并且可以做到线程安全。(加锁是由于 cls() 调用不是原子操作,在 GIL 存在的情况下也存在线程竞争)

from functools import wraps
from threading import Lock
from typing import Callable, Type, TypeVar

T = TypeVar("T")


def singleton(cls: Type[T]) -> Callable[..., T]:
    """线程安全的单例模式装饰器

    用法:
    ```python
    @singleton
    class C:
        ...
    ```
    """
    _instances = {}
    _lock = Lock()

    @wraps(cls)
    def _get_instance(*args, **kwargs):
        with _lock:
            if cls not in _instances:
                _instances[cls] = cls(*args, **kwargs)
        return _instances[cls]

    return _get_instance


class SingletonMeta(type):
    """线程安全的单例元类

    用法:
    ```python
    class C(metaclass=SingletonMeta):
        ...
    ```
    """

    _instances = {}
    _lock: Lock = Lock()

    def __call__(cls, *args, **kwargs):
        with cls._lock:
            if cls not in cls._instances:
                instance = super().__call__(*args, **kwargs)
                cls._instances[cls] = instance
        return cls._instances[cls]

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants