我需要一个跟踪实例化次数的Python类

4 投票
4 回答
2518 浏览
提问于 2025-04-15 12:37

我需要一个类,功能是这样的:

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

这是我尝试的代码:

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

这个代码能按我想要的方式工作,但我在想有没有更符合Python风格的方法来实现它。

4 个回答

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可以从多个线程中实例化。

5

滥用装饰器和 metaclass(元类)。

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

你可以通过经常看到双下划线的名字来判断这段代码是不是 Python 风格的。(开玩笑的,开玩笑的...)

14

不,这样挺好的。

来自《Python之禅》的一句话:“简单胜于复杂。”

这样做没问题,而且很清楚你在做什么,别把它搞复杂。可以把它命名为counter之类的,但除此之外,你的做法在Python的风格上是没问题的。

撰写回答