どこからではなく、クラスの静的関数によってのみ呼び出されるプライベートコンストラクターを作成するにはどうすればよいですか?
プライベートコンストラクターを作成するにはどうすればよいですか?
本質的に、それは不可能です両方ともpythonは、あなたがその他OOP言語、およびpythonは強制プライバシーではないため、特定のメソッド/プロパティがshouldプライベートと見なされます。詳しく説明します...
最初:pythonで見つけることができるコンストラクターに最も近いものは ___new__
_ method ですが、これはほとんど使用されません(通常は___init__
_、作成されたばかりのオブジェクトを変更します(実際、最初のパラメーターとして既にself
を持っています)。
とにかく、pythonは全員が同意する大人であるという仮定に基づいているため、他の言語のようにprivate/publicは強制されません。
他のレスポンダーが言及しているように、「プライベート」であるメソッドは通常、1つまたは2つのアンダースコア(__private
_または___private
_)が先頭に追加されます。 2つの違いは、後者はメソッドの名前をスクランブルするため、オブジェクトのインスタンス化の外部から呼び出すことはできませんが、前者はそうではありません。
たとえば、クラスA
が_private(self)
と__private(self)
の両方を定義している場合:
_>>> a = A()
>>> a._private() # will work
>>> a.__private() # will raise an exception
_
通常、単一のアンダースコアを使用する必要があります。特にユニットテストの場合、アンダースコアが2つあると非常に注意が必要になります。
HTH!
_
および__
プレフィックスは、オブジェクトのインスタンス化を特定の「ファクトリー」に制限するソリューションを提供しませんが、Pythonは強力なツールボックスであり、望ましい振る舞いは複数の方法で実現できます(Zの@Jesse Wが示したように)。クラスを公開する(isinstance
などを許可する)が、クラスによってのみ構築が可能であることを保証する可能なソリューションを次に示します。 -メソッド:
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
create
クラスメソッドを使用してオブジェクトを作成します。
>>> OnlyCreatable.create("I'm a test")
<__main__.OnlyCreatable object at 0x1023a6f60>
create
クラスメソッドの作成を使用せずにオブジェクトを構築しようとすると、アサーションのために失敗します。
>>> OnlyCreatable(0, "I'm a test")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in __init__
AssertionError: OnlyCreatable objects can only be created using OnlyCreatable.create
create
クラスメソッドの作成を模倣してオブジェクトを作成しようとすると、OnlyCreatable.__createKey
のコンパイラーのマングリングが原因で失敗します。
>>> OnlyCreatable(OnlyCreatable.__createKey, "I'm a test")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'OnlyCreatable' has no attribute '__createKey'
クラスメソッドの外でOnlyCreatable
を構築する唯一の方法は、OnlyCreatable.__create_key
の値を知ることです。このクラス属性の値は実行時に生成され、名前には__という接頭辞が付き、アクセス不可としてマークされるため、この値を取得したりオブジェクトを構築したりすることは事実上「不可能」です。
まだ誰もこれに言及していないので、namesがどのスコープで見えるかをかなり制御できます-そして、lots使用可能なスコープ。ここにあります 二 threeクラスの構築をファクトリメソッドに制限する他の方法:
#Define the class within the factory method
def factory():
class Foo:
pass
return Foo()
OR
#Assign the class as an attribute of the factory method
def factory():
return factory.Foo()
class Foo:
pass
factory.Foo = Foo
del Foo
(注:これにより、クラスを外部から参照できます(たとえば、isinstance
チェック用)が、直接インスタンス化することになっていないことは明らかです。)
OR
#Assign the class to a local variable of an outer function
class Foo:
pass
def factory_maker():
inner_Foo=Foo
def factory():
return inner_Foo()
return factory
factory = factory_maker()
del Foo
del factory_maker
これにより、impossible(少なくとも、少なくとも1つのマジック(二重アンダースコア)プロパティを使用せずに)Foo
クラスにアクセスできますが、複数の関数がそれを使用できるようにします(グローバルFoo名を削除する前にそれらを定義することにより)。
さらに、先頭または末尾のアンダースコアを使用した次の特別な形式が認識されます(これらは通常、大文字と小文字の組み合わせと組み合わせることができます)。
_
_single_leading_underscore
_:弱い「内部使用」インジケータ。例えば。 「_from M import *
_」は、名前がアンダースコアで始まるオブジェクトをインポートしません。_
single_trailing_underscore_
_:Pythonキーワード、たとえばTkinter.Toplevel(master, class_='ClassName')
との競合を避けるために慣例により使用されます_
__double_leading_underscore
_:クラス属性に名前を付けるとき、名前マングリングを呼び出します(クラスFooBar内で、___boo
_は__FooBar__boo
_になります。以下を参照)。_
__double_leading_and_trailing_underscore__
_:ユーザー制御の名前空間に存在する「マジック」オブジェクトまたは属性。例えば。 ___init__
_、___import__
_、または___file__
_。そのような名前を発明しないでください。文書化されているとおりにのみ使用してください。
第一に、「コンストラクタ」という用語はPythonには適用されません。なぜなら、__init__()
メソッドは1つの役割を果たしますが、オブジェクトが既に作成され初期化が必要なときに呼び出されるメソッドにすぎないためです。
Pythonのクラスのすべてのメソッドはパブリックです。通常、プログラマはメソッドの名前に_
または__
を使用して「プライベート」メソッドをマークします。例:
# inheriting from object is relevant for Python 2.x only
class MyClass(object):
# kinda "constructor"
def __init__(self):
pass
# here is a "private" method
def _some_method(self):
pass
# ... and a public one
def another_method(self):
pass
class MongoConn(object):
@classmethod
def instance(cls):
if not hasattr(cls, '_instance'):
cls._instance = cls()
return cls._instance
def __init__(self):
assert not hasattr(self.__class__, '_instance'), 'Do not call constructor directly!'
単一のインスタンスが必要な場合。