Skip to content

Instantly share code, notes, and snippets.

@vielhuber
Last active June 30, 2025 09:48
Show Gist options
  • Save vielhuber/5fa4012ae319fdebcff31fe3c1e9d234 to your computer and use it in GitHub Desktop.
Save vielhuber/5fa4012ae319fdebcff31fe3c1e9d234 to your computer and use it in GitHub Desktop.
object oriented programming multiple classes as singletons #python

/classes/__init__.py

from .foo import Foo
from .bar import Bar

foo = Foo()
bar = Bar()

# this enables "import *"
__all__ = [
    "foo",
    "bar"
]

/classes/foo.py

class Foo:

    _instance = None

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

    def __init__(self):
        if not hasattr(self, "_initialized"):
            self._initialized = True

    def test(self):
        print("foo")

/classes/bar.py

class Bar:

    _instance = None

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

    def __init__(self):
        if not hasattr(self, "_initialized"):
            self._initialized = True

    def test(self):
        print("bar")

/script.py

from classes import foo, bar
#from classes import *

class Test:

    def __init__(self):
        self.var1 = 42

    async def main(self):
        foo.test()
        bar.test()

if __name__ == "__main__":
  test = Test()
  test.main()

/start.py

import app.main as main

if __name__ == "__main__":
    main.run()

/app/main.py

from app.utils.singletons import test1

def run():
    test1.start()

/app/singletons/test1.py

from app.utils.singletons import test2, test3
from app.utils.helpers import singleton
from app.classes.test4 import Test4

@singleton
class Test1:
    def start(self):
        print(type(test2))
        print(test2.var)  # None
        print(test3.var)  # None
        test2.setVars("variable in test2", "variable in test3")
        print(test2.var)  # "variable in test2"
        print(test3.var)  # "variable in test3"
        test4 = Test4()
        test4.echo()

/app/singletons/test2.py

from app.utils.singletons import test3
from app.utils.helpers import singleton

@singleton
class Test2:
    def __init__(self):
        self.var = None
    def setVars(self, var1, var2):
        self.var = var1
        test3.var = var2

/app/singletons/test3.py

from app.utils.helpers import singleton

@singleton
class Test3:
    def __init__(self):
        self.var = None

/app/classes/test4.py

import app.utils.singletons as singletons

class Test4:
    def echo(self):
        print("Test4")
        print(singletons.test3.var)

/app/utils/helpers.py

def singleton(cls):
    _instance = None
    def wrapper(*args, **kwargs):
        nonlocal _instance
        if _instance is None:
            _instance = cls(*args, **kwargs)
            if not hasattr(_instance, "_initialized"):
                _instance._initialized = True
        return _instance
    return wrapper

/app/utils/singletons.py

_initialized = False

test1 = None
test2 = None
test3 = None

def bootstrap():
    global _initialized
    if _initialized:
        return

    global test1
    global test2
    global test3

    import app.singletons.test1 as m1
    import app.singletons.test2 as m2
    import app.singletons.test3 as m3

    from app.singletons.test1 import Test1
    from app.singletons.test2 import Test2
    from app.singletons.test3 import Test3

    test1 = Test1()
    test2 = Test2()
    test3 = Test3()

    m1.test2 = test2
    m1.test3 = test3

    m2.test1 = test1
    m2.test3 = test3

    m3.test1 = test1
    m3.test2 = test2

    _initialized = True

bootstrap()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment