How do I create a private constructor which should be called only by the static function of the class and not from else where?
相关问题
- how to define constructor for Python's new Nam
- streaming md5sum of contents of a large remote tar
- How to get the background from multiple images by
- Evil ctypes hack in python
- Correctly parse PDF paragraphs with Python
If you want a single instance.
Quoting the Python style guide (PEP 8):
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 (allowingisinstance
etc.) but ensures construction is only possible by class-methods:Constructing an object with the
create
class-method:When attempting to construct an object without using the
create
class-method creation fails due to the assertion:If attempting to create an object by mimicking the
create
class-method creation fails due to compiler mangling ofOnlyCreatable.__createKey
.The only way to construct
OnlyCreatable
outside of a class-method is to know the value ofOnlyCreatable.__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.As no-one has mentioned this yet -- you can have considerable control over what names are visible in what scopes -- and there are lots of scopes available. Here are
twothree other ways to limit construction of a class to a factory method:OR
(Note: This still allows the class to be referred to from outside (for
isinstance
checks, for example), but it makes it pretty obvious that you aren't supposed to instantiate it directly.)OR
This makes it impossible (at least, without using at least one magic (double underscore) property) to access the
Foo
class, but still allows multiple functions to use it (by defining them before deleting the global Foo name.In essence, it's impossible both because python does not use constructors the way you may think it does if you come from other OOP languages and because python does not enforce privacy, it just has a specific syntax to suggest that a given method/property should be considered as private. Let me elaborate...
First: the closest to a constructor that you can find in python is the
__new__
method but this is very very seldom used (you normally use__init__
, which modify the just created object (in fact it already hasself
as first parameter).Regardless, python is based on the assumption everybody is a consenting adult, thus private/public is not enforced as some other language do.
As mentioned by some other responder, methods that are meant to be "private" are normally prepended by either one or two underscores:
_private
or__private
. The difference between the two is that the latter will scramble the name of the method, so you will be unable to call it from outside the object instantiation, while the former doesn't.So for example if your class
A
defines both_private(self)
and__private(self)
:You normally want to use the single underscore, as - especially for unit testing - having double underscores can make things very tricky....
HTH!
Fist of all, the term "constructor" does not apply to Python, because, although
__init__()
method plays a role of one, it is just a method which is called when an object has already been created and requires initialization.Every method of a class in Python is public. Generally programmers mark "private" methods with
_
or__
in the name of a method, e.g.: