4

次のように機能するクラスが必要です。

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

これが私の試みです:

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

必要に応じて機能しますが、もっとpythonicな方法があるのではないかと思います。

4

4 に答える 4

13

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

The Zen of Python より: 「シンプルは複雑よりも優れている」。

それはうまく機能し、何をしているのかが明確です。複雑にしないでください。多分それcounterか何かに名前を付けるかもしれませんが、それ以外はpythonicが行くところまで行くのは良いことです.

于 2009-07-02T00:14:04.627 に答える
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 であることがわかります。(冗談、冗談…)

于 2009-07-02T01:48:41.643 に答える
4

スレッドの安全性について心配したい場合 (クラス変数をインスタンス化する複数のスレッドから変更できるようにするため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複数のスレッドからインスタンス化できるようになりました。

于 2009-07-02T13:10:47.777 に答える