質問

オブジェクトにメンバーがあるかどうかを定期的にチェックしたい。例は、関数内のシングルトンの作成です。そのためには、次のように hasattr を使用できます。

class Foo(object):
    @classmethod
    def singleton(self):
        if not hasattr(self, 'instance'):
            self.instance = Foo()
        return self.instance

ただし、これも実行できます。

class Foo(object):
    @classmethod
    def singleton(self):
        try:
            return self.instance
        except AttributeError:
            self.instance = Foo()
            return self.instance

1つの方法は他の方法より優れていますか?

編集: @classmethod を追加しました...しかし、質問はシングルトンを作る方法ではなく、チェックする方法について ではないことに注意してくださいオブジェクト内のメンバーの存在。

編集:その例の典型的な使用法は次のとおりです。

s = Foo.singleton()

その後、 s は、毎回同じタイプの Foo のオブジェクトです。そして、通常、メソッドは何度も呼び出されます。

役に立ちましたか?

解決

これらは2つの異なる方法論です。№ 1はLBYL(ジャンプする前に見てください)および№ 2はEAFP(許可よりも許しを求める方が簡単です)。

Pythonistasは通常、EAFPの方が優れていることを提案します。引数は"プロセスをテストしてから自分で作成するまでの間にプロセスがファイルを作成するとどうなりますか?この議論はここでは当てはまりませんが、一般的な考え方です。例外を too 例外として扱うべきではありません。

あなたの場合のパフォーマンスについて—例外の作成中( try キーワード)の例外マネージャーのセットアップはCPythonで非常に安価であるため( raise キーワードおよび内部例外の作成)は比較的高価です—メソッド№ 2を使用すると、例外は1回だけ発生します。その後、プロパティを使用するだけです。

他のヒント

時間を測定しようとしました:

class Foo(object):
    @classmethod
    def singleton(self):
        if not hasattr(self, 'instance'):
            self.instance = Foo()
        return self.instance



class Bar(object):
    @classmethod
    def singleton(self):
        try:
            return self.instance
        except AttributeError:
            self.instance = Bar()
            return self.instance



from time import time

n = 1000000
foo = [Foo() for i in xrange(0,n)]
bar = [Bar() for i in xrange(0,n)]

print "Objs created."
print


for times in xrange(1,4):
    t = time()
    for d in foo: d.singleton()
    print "#%d Foo pass in %f" % (times, time()-t)

    t = time()
    for d in bar: d.singleton()
    print "#%d Bar pass in %f" % (times, time()-t)

    print

私のマシン:

Objs created.

#1 Foo pass in 1.719000
#1 Bar pass in 1.140000

#2 Foo pass in 1.750000
#2 Bar pass in 1.187000

#3 Foo pass in 1.797000
#3 Bar pass in 1.203000

try / exceptの方が速いようです。私にとっても読みやすいようです。とにかく場合によって異なりますが、このテストは非常に簡単だったので、もっと複雑なテストが必要になるかもしれません。

例外は、例外的な状態をモデル化する必要があるため、どのケースが「典型的な」かによって異なります。したがって、典型的なケースが instance 属性が存在する必要がある場合、2番目のコードスタイルを使用します。 instance を持たないことが instance を持っているのと同じくらい一般的な場合、最初のスタイルを使用します。

シングルトンを作成する特定のケースでは、最初にシングルトンを作成するのが典型的なユースケースであるため、最初のスタイルを使用する傾向があります。 :-)

それを使用する方法で少しトピックから外れています。シングルトンは過大評価されており、「共有状態」はメソッドは同様に効果的で、ほとんどの場合、Pythonでは非常にきれいです:

class Borg:
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state
    # and whatever else you want in your class -- that's all!

今度は毎回:

obj = Borg()

同じ情報を持つか、または多少同じインスタンスになります。

scroll top