2

I'm developing a python library which interfaces its functionalities through a class. The user of the library needs to intantiate this when first importing it into their project. After this the library object would have some state which I want to be sharable across the entire project of the user.

Something like this:

Library

class Lib():

  def __init__(self, msg):
    self.msg = msg

  def print_msg():
    print(self.msg)

submod1

from lib import Lib

def test():
  # something like this
  Lib.print_msg()

submod2

from lib import Lib

def test():
  # something like this
  Lib.print_msg()

User's main

from lib import Lib:
import submod1, submod2

lib = Lib('message')

submod1.test()
submod2.test()

Output

message
message
martineau
  • 119,623
  • 25
  • 170
  • 301
  • 3
    Create your library object as a singleton. Hide the class itself, expose the singleton object – rdas Feb 06 '20 at 17:43

2 Answers2

3

Looks like a Singleton class would be a good fit for your use case. There are multiple ways to implement a singleton class in python. Refer to this answer for more detailed explanation.

Though as for your use case you can do something like this:

class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            # don't want __init__ to be called every time
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]


class Lib(metaclass=Singleton):
    def __init__(self, msg):
        self.msg = msg

    def print_msg():
        print(self.msg)

submod1

from lib import Lib

    def test():
        Lib().print_msg()

main file

from lib import Lib:
import submod1, submod2

    lib = Lib('message')

    submod1.test()
    submod2.test()
martineau
  • 119,623
  • 25
  • 170
  • 301
rohanmehto2
  • 910
  • 1
  • 7
  • 19
  • What does the comment mean in the metaclass? Thanks – Samarthya Choudhary Feb 06 '20 at 17:53
  • 1
    Refer the asnwer which i linked to it explains it in detail. If you want __init__ to be called each time add an else statement with cls._instances[cls].__init__(*args, **kwargs) – rohanmehto2 Feb 06 '20 at 17:55
  • How are you accessing "self.msg" from "print_msg" if there is no "self" argument? I'm getting errors trying to run the code. Thanks. – Nedo Jun 19 '23 at 15:02
1

Lib.py:

class Lib:
    msg = ""
    __init__ = None

    @classmethod
    def print_msg(cls):
        print(cls.msg)

Maybe something like this?

First use:

Lib.msg = "abc"
Lib.print_msg()

Second use:

Lib.print_msg()
Dennis
  • 2,249
  • 6
  • 12
  • Thanks for the answer. Will the value of msg be preserved when importing the library in other submodules of the project? – Samarthya Choudhary Feb 06 '20 at 17:58
  • They will be preserved for the entire time your Python interpreter is running. Imports are cached, so new imports don't re-evaluate the code within one program, even if the imports happen in different modules. – Dennis Feb 06 '20 at 18:02