Private Constructor in Python

前端 未结 8 1994
栀梦
栀梦 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:36

    The _ and __ prefixes don't offer a solution to restricting instantiation of an object to a specific 'factory', however Python is a powerful toolbox and the desired behaviour can be achieved in more than one way (as @Jesse W at Z has demonstrated). Here is a possible solution that keeps the class publicly visible (allowing isinstance etc.) but ensures construction is only possible by class-methods:

    class OnlyCreatable(object):
    
        __create_key = object()
    
        @classmethod
        def create(cls, value):
            return OnlyCreatable(cls.__create_key, value)
    
        def __init__(self, create_key, value):
            assert(create_key == OnlyCreatable.__create_key), \
                "OnlyCreatable objects must be created using OnlyCreatable.create"
            self.value = value
    

    Constructing an object with the create class-method:

    >>> OnlyCreatable.create("I'm a test") 
    <__main__.OnlyCreatable object at 0x1023a6f60>
    

    When attempting to construct an object without using the create class-method creation fails due to the assertion:

    >>> OnlyCreatable(0, "I'm a test")
    Traceback (most recent call last):
      File "", line 1, in 
      File "", line 11, in __init__
    AssertionError: OnlyCreatable objects can only be created using OnlyCreatable.create
    

    If attempting to create an object by mimicking the create class-method creation fails due to compiler mangling of OnlyCreatable.__createKey.

    >>> OnlyCreatable(OnlyCreatable.__createKey, "I'm a test")
    Traceback (most recent call last):
      File "", line 1, in 
    AttributeError: type object 'OnlyCreatable' has no attribute '__createKey'
    

    The only way to construct OnlyCreatable outside of a class-method is to know the value of OnlyCreatable.__create_key. Since this class-attribute's value is generated at runtime and it's name is prefixed with __ marking it as inaccessible it is effectively 'impossible' to obtain this value and/or construct the object.

提交回复
热议问题