Advertisement
mmandrille

Untitled

Aug 9th, 2022
1,009
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.28 KB | None | 0 0
  1. """ The Singleton Pattern
  2.  
  3. Notes:
  4.  
  5. While there are multiple ways to implement the Singleton pattern, the point of
  6. the Singleton pattern is to expose only one object without the possiblity to
  7. create multiple _instances of the object.
  8.  
  9. It is important to note that if your need for this design pattern can be met by
  10. a simple class-less python module (within a .py file), that solution is simpler and
  11. usually preferable. One limitation of using a module's namespace instead of a Singleton
  12. is that a module cannot be constructed with arguments and cannot have properties.
  13.  
  14. Extra:
  15. I strongly recommend the 'Borg' pattern as a more elegant alternative (see borg.py). It
  16. usually meets all the needs of a Singleton with a more classical OOP approach.
  17.  
  18. """
  19. # Import definition
  20. from datetime import datetime
  21.  
  22. # Classes Definition
  23. class NamedSingletonObject(object):
  24.     instances = {} # We will keep created instances here
  25.     class __NamedSingletonObject():
  26.         def __init__(self, name:str):
  27.             self.name = name
  28.  
  29.         def __str__(self):
  30.             return f"{self.name}({id(self)})"
  31.  
  32.     def __new__(cls, name): # __new__ method created object before __init__ load values.
  33.         # Check if already exist
  34.         print(f"\nWe are creating: {name} Singletone")
  35.         if name not in cls.instances.keys():
  36.             print(f"There is not a '{name}' singleton. Creating...")
  37.             # Create if not
  38.             cls.instances[name] = cls.__NamedSingletonObject(name)
  39.         # Return correct singleton
  40.         return cls.instances.get(name)
  41.  
  42. class Logger(NamedSingletonObject):
  43.     """
  44.    A file-based message logger with the following properties
  45.    Attributes:
  46.    file_name: a string representing the full path of the log file to which
  47.    this logger will write its messages
  48.    """
  49.     def __new__(self, filename):
  50.         """Return a Logger object whose file_name is *file_name*"""
  51.         super().__new__(self, filename)
  52.         logger = self.instances.get(filename)
  53.         logger.file_name = filename
  54.         return logger
  55.  
  56.     def _write_log(self, level, msg):
  57.         """Writes a message to the file_name for a specific Logger instance"""
  58.         with open(self.file_name, "a") as log_file:
  59.             log_file.write(f"[{level}]-{datetime.now()} {msg}\n")
  60.    
  61.     # We define a method for every level, we could need specific treatments
  62.     def critical(self, msg):
  63.         self._write_log("CRITICAL",msg)
  64.     def error(self, msg):
  65.         self._write_log("ERROR", msg)
  66.     def warn(self, msg):
  67.         self._write_log("WARN", msg)
  68.     def info(self, msg):
  69.         self._write_log("INFO", msg)
  70.     def debug(self, msg):
  71.         self._write_log("DEBUG", msg)          
  72.  
  73. # Testing
  74. if __name__ == '__main__':
  75.     # We create 2 loggers
  76.     log1 = Logger("primary.log")
  77.     print(f"obj1: {log1.file_name} ({id(log1)})")
  78.    
  79.     log2 = Logger("secundary.log")
  80.     print(f"obj1: {log1.file_name} ({id(log1)})")
  81.     print(f"obj2: {log2.file_name} ({id(log2)})")
  82.  
  83.     print(f"\nWe check if are't the same object: {log1 is not log2}")
  84.     assert True == (log1 is not log2)
  85.     # We call Logger with same name:
  86.     log3 = Logger("primary.log")
  87.     print(f"We check if are the same object 1 & 3: {log1 is log3}")
  88.     assert True == (log1 is log3)
  89.    
  90.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement