次のように機能するクラスが必要です。
>>> a=Foo()
>>> b=Foo()
>>> c=Foo()
>>> c.i
3
これが私の試みです:
class Foo(object):
i = 0
def __init__(self):
Foo.i += 1
必要に応じて機能しますが、もっとpythonicな方法があるのではないかと思います。
いいえ。それはかなり良いです。
The Zen of Python より: 「シンプルは複雑よりも優れている」。
それはうまく機能し、何をしているのかが明確です。複雑にしないでください。多分それcounter
か何かに名前を付けるかもしれませんが、それ以外はpythonicが行くところまで行くのは良いことです.
デコレータとメタクラスの悪用。
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 であることがわかります。(冗談、冗談…)
スレッドの安全性について心配したい場合 (クラス変数をインスタンス化する複数のスレッドから変更できるようにするため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
Foo
複数のスレッドからインスタンス化できるようになりました。