2009-07-02 1 views
4
私はこのように動作しますクラスが必要

私はそれがインスタンス化される回数のトラックを保つPythonのクラスが必要

class Foo(object): 
    i = 0 
    def __init__(self): 
     Foo.i += 1 

それは、必要に応じて動作します。ここでは

>>> a=Foo() 
>>> b=Foo() 
>>> c=Foo() 
>>> c.i 
3 

は私の試みですしかし、私はそれを行うためにもっとpythonicな方法があるのだろうかと思います。

+1

pythonicとは何ですか?それはPythonで動作する場合は...そのPythonではない** ic **? – Victor

+0

他の方法を実装する時間を無駄にする必要はありません – fuentesjr

+0

私は「python」を「pythonイディオム」を意味すると解釈します。 JavaプログラマのようにPythonを書くことは可能です。これは、必ずしも最高の品質やスタイルを示すわけではありません。 – duffymo

答えて

11

いいえ。それはかなり良いです。

From The Python of Zen:「シンプルは複雑なものより優れています。

それはうまく動作し、あなたがやっていることではっきりしていて、それを複雑にしません。たぶんそれはcounterか何かと名付けられますが、それ以外にはあなたはpythonicに行くのが良いと言います。

+1

たぶん私は質問に代えて私のコメントをここに載せるべきです:私はちょうど興味があります、このスレッドセーフのようなものですか? Fooを複数のスレッドからインスタンス化し、適切な数を持つことができるでしょうか? – Tom

+0

@Tom:良い質問です。私は正直には分かりませんが、私はそれがそうすると思います。 –

+0

私はここで質問した:http://stackoverflow.com/questions/1072821/is-modifying-a-class-variable-in-python-threadsafe。 – Tom

5

デコレータとメタクラスの悪用。

def counting(cls): 
    class MetaClass(getattr(cls, '__class__', type)): 
     __counter = 0 
     def __new__(meta, name, bases, attrs): 
      old_init = attrs.get('__init__') 
      def __init__(*args, **kwargs): 
       MetaClass.__counter += 1 
       if old_init: return old_init(*args, **kwargs) 
      @classmethod 
      def get_counter(cls): 
       return MetaClass.__counter 
      new_attrs = dict(attrs) 
      new_attrs.update({'__init__': __init__, 'get_counter': get_counter}) 
      return super(MetaClass, meta).__new__(meta, name, bases, new_attrs) 
    return MetaClass(cls.__name__, cls.__bases__, cls.__dict__) 

@counting 
class Foo(object): 
    pass 

class Bar(Foo): 
    pass 

print Foo.get_counter() # ==> 0 
print Foo().get_counter() # ==> 1 
print Bar.get_counter() # ==> 1 
print Bar().get_counter() # ==> 2 
print Foo.get_counter() # ==> 2 
print Foo().get_counter() # ==> 3 

二重の下線付きの名前を頻繁に使用することでPythonicと言うことができます。

+4

+1:これは嫌です。 – Thomas

4

クラス変数がFooをインスタンス化している複数のスレッドから変更できるように、スレッドの安全性を心配したい場合は、上記の答えが正しいです。私はスレッドの安全性についてこの質問をしましたhere。要約すると、あなたはこのような何かしなければならないでしょう。今Foo

from __future__ import with_statement # for python 2.5 

import threading 

class Foo(object): 
    lock = threading.Lock() 
    instance_count = 0 

    def __init__(self): 
    with Foo.lock: 
     Foo.instance_count += 1 

を複数のスレッドからインスタンス化することができます。

関連する問題