Private Constructor in Python

前端 未结 8 1997
栀梦
栀梦 2020-12-13 23:19

How do I create a private constructor which should be called only by the static function of the class and not from else where?

8条回答
  •  情书的邮戳
    2020-12-13 23:41

    You can achieve something to this effect with an abstract class. Any instance attributes that need defining in the "private constructor" can be abstract properties. Your factory class method then builds its own concrete class by populating these abstract attributes, as well as doing any other initialisation work such as data validation.

    from abc import ABC, abstractmethod
    
    class Foo(ABC):
        @property
        @abstractmethod
        def _a(self) -> int:
            pass
    
        def bar(self) -> int:
            return self._a + 1
    
        @classmethod
        def from_values(cls, a: int) -> 'Foo':
            class _Foo(cls):
                def __init__(self, __a):
                    self.__a = __a
    
                @property
                def _a(self):
                    return self.__a
    
            return _Foo(a)
    
    Foo()  # TypeError: Can't instantiate abstract class ...
    Foo.from_values(1).bar()  # 1
    

    If you find you need no abstract attributes on Foo, you won't get the TypeError when calling Foo(). In that case you can either rely on the inheritance from ABC as documentation, or define a dummy attribute for safety.

    Possible tweaks

    • Need mutable instance attributes? Add setters.
    • Don't care about the difference between class and instance attributes? Simplify with

      class _Foo(cls):
          _a = a
      
      return _Foo()
      

提交回复
热议问题