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

没有。这很不错。

来自 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

如果您想担心线程安全(以便可以从正在实例化Foos 的多个线程中修改类变量),则上述答案是正确的。我在这里问了这个关于线程安全的问题。总之,你必须做这样的事情:

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 回答
0

我们可以使用装饰器吗?所以例如..

class ClassCallCount:
    def __init__(self,dec_f):
        self._dec_f = dec_f
        self._count = 0

    def __call__(self, *args, **kwargs):
        self._count +=1
        return self._dec_f(*args, **kwargs)

    def PrintCalled(self):
        return (self._count)


@ClassCallCount
def somefunc(someval):
    print ('Value : {0}'.format(someval))



    somefunc('val.1')
    somefunc('val.2')
    somefunc('val.3')
    somefunc('val.4')
    ## Get the # of times the class was called
    print ('of times class was called : {0}'.format(somefunc._count))
于 2020-03-25T17:55:57.150 回答