【问题标题】:I need a Python class that keep tracks of how many times it is instantiated我需要一个 Python 类来跟踪它被实例化的次数
【发布时间】:2009-07-02 00:12:36
【问题描述】:

我需要一个像这样工作的类:

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

这是我的尝试:

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

它按要求工作,但我想知道是否有更pythonic的方式来做到这一点。

【问题讨论】:

  • pythonic这个词是什么意思?如果它在python中工作......那不是pythonic吗?
  • 无需浪费时间实施任何其他方式
  • 我认为“pythonic”的意思是“在python成语中”。像 Java 程序员一样编写 Python 是可能的,但这并不一定会展示其最好的品质或风格。
  • Pythonic 的意思是“惯用的 Python”或遵循一般 Python 约定和准则的代码。例如,与 Java 开发人员明确编写的 Python 代码相反。区别就很明显了。
  • 哇。不敢相信我们基本上写了相同的回复......

标签: python class instances


【解决方案1】:

不。挺好的。

来自 Python 之禅:“简单胜于复杂。”

这很好,并且清楚你在做什么,不要让它复杂化。也许将其命名为 counter 或其他名称,但除此之外,您可以继续使用 pythonic。

【讨论】:

  • 也许我应该在这里发表我的评论,而不是在这个问题上:我只是好奇,像这样的线程安全吗?你能从多个线程中实例化 Foo 并有适当的计数吗?
  • @Tom:好问题。老实说,我不确定,但我认为确实如此。
  • 我在这里问了这个问题:stackoverflow.com/questions/1072821/….
【解决方案2】:

滥用装饰器和元类。

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。 (开玩笑,开玩笑……)

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

      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))
      

      【讨论】:

      • 这是一个新问题还是一个答案?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-29
      • 2019-11-17
      • 2023-01-03
      • 1970-01-01
      相关资源
      最近更新 更多