わかりました、これが実際のシナリオです: 私はアプリケーションを書いていて、特定の種類のファイルを表すクラスがあります (私の場合、これは写真ですが、その詳細は問題とは無関係です)。Photograph クラスの各インスタンスは、写真のファイル名に対して一意である必要があります。
問題は、ユーザーがアプリケーションにファイルをロードするように指示した場合、ファイルが既にロードされていることを識別し、同じファイル名で重複するインスタンスを作成するのではなく、そのファイル名の既存のインスタンスを使用できるようにする必要があることです。
私には、これはメモ化を使用するのに適した状況のように思えます。その例はたくさんありますが、この場合、通常の関数をメモ化するだけでなく、メモ化する必要があります__init__()
。これは問題を引き起こし__init__()
ます。新しいインスタンスが既に作成されているため、呼び出されるまでには手遅れだからです。
私の研究で、私は Python の__new__()
メソッドを見つけ、実際に動作する簡単な例を書くことができましたが、実際のオブジェクトでそれを使用しようとするとバラバラになり、理由がわかりません (私ができる唯一のこと)私の現実世界のオブジェクトは、実際には制御できない他のオブジェクトのサブクラスであったため、このアプローチにはいくつかの非互換性があったと考えてください)。これは私が持っていたものです:
class Flub(object):
instances = {}
def __new__(cls, flubid):
try:
self = Flub.instances[flubid]
except KeyError:
self = Flub.instances[flubid] = super(Flub, cls).__new__(cls)
print 'making a new one!'
self.flubid = flubid
print id(self)
return self
@staticmethod
def destroy_all():
for flub in Flub.instances.values():
print 'killing', flub
a = Flub('foo')
b = Flub('foo')
c = Flub('bar')
print a
print b
print c
print a is b, b is c
Flub.destroy_all()
これを出力する:
making a new one!
139958663753808
139958663753808
making a new one!
139958663753872
<__main__.Flub object at 0x7f4aaa6fb050>
<__main__.Flub object at 0x7f4aaa6fb050>
<__main__.Flub object at 0x7f4aaa6fb090>
True False
killing <__main__.Flub object at 0x7f4aaa6fb050>
killing <__main__.Flub object at 0x7f4aaa6fb090>
パーフェクトだ!指定された 2 つの一意の ID に対して作成されたインスタンスは 2 つだけで、Flub.instances には明らかに 2 つのみがリストされています。
しかし、私が使用していたオブジェクトでこのアプローチをとろうとすると、__init__()
2 ではなく 0 の引数しか取らなかったという、あらゆる種類の無意味なエラーが発生し__init__()
ました。 . 完全に奇妙です。
しばらく格闘した後、私は基本的にすべての黒魔術をあきらめて、すべての黒魔術をと呼ば__new__()
れる staticmethod に移動しました。get
Photograph.get(filename)
Photograph(filename)
Photograph.instances
ここで私がどこで間違ったのか誰か知っていますか? これを行うためのより良い方法はありますか?
それについての別の考え方は、シングルトンに似ているということです。ただし、グローバルなシングルトンではなく、ファイル名ごとにシングルトンである点が異なります。
すべてをまとめて見たい場合は、これが staticmethod get を使用した私の実際のコードです。