mobuchowski opened a new pull request, #32218:
URL: https://github.com/apache/airflow/pull/32218

   Singleton implementation using overloaded `__new__` did not work - it always 
called init on instance creation.
   
   > If 
[__new__()](https://docs.python.org/3/reference/datamodel.html#object.__new__) 
does not return an instance of cls, then the new instance’s 
[__init__()](https://docs.python.org/3/reference/datamodel.html#object.__init__)
 method will not be invoked.
   
   But it is an cls instance in this case.
   
   ```python
   Python 3.9.9 (main, Nov 29 2021, 15:18:55)
   [Clang 13.0.0 (clang-1300.0.29.3)] on darwin
   Type "help", "copyright", "credits" or "license" for more information.
   >>> class A:
   ...     _instance = None
   ...     def __new__(cls):
   ...         if cls._instance is None:
   ...             cls._instance = super().__new__(cls)
   ...         return cls._instance
   ...
   >>> class A:
   ...     _instance = None
   ...     def __new__(cls):
   ...         if cls._instance is None:
   ...             cls._instance = super().__new__(cls)
   ...         return cls._instance
   ...     def __init__(self):
   ...         print("init")
   ...
   >>> A()
   init
   <__main__.A object at 0x1028c4a60>
   >>> A()
   init
   <__main__.A object at 0x1028c4a60>
   >>>
   ```
   
   This changes it to metaclass-based approach that does not have this bug.
   
   ```python
   Python 3.9.9 (main, Nov 29 2021, 15:18:55)
   [Clang 13.0.0 (clang-1300.0.29.3)] on darwin
   Type "help", "copyright", "credits" or "license" for more information.
   >>> class Singleton(type):
   ...     """Metaclass that allows to implement singleton pattern."""
   ...     _instances: dict = {}
   ...     def __call__(cls, *args, **kwargs):
   ...         if cls not in cls._instances:
   ...             cls._instances[cls] = super().__call__(*args, **kwargs)
   ...         return cls._instances[cls]
   ...
   >>> class A(metaclass=Singleton):
   ...     def __init__(self):
   ...         print("init")
   ...
   >>> A()
   init
   <__main__.A object at 0x10268b0a0>
   >>> A()
   <__main__.A object at 0x10268b0a0>
   >>>
   ```
   
   I would prefer to have singletons implemented as modules, as in some other 
places, but in this case those are already classes - I think metaclass based 
approach it does not change their API while fixing the issue.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to