如何静态覆盖__iter__和__contains__?

时间:2015-02-26 16:46:28

标签: python class iterator

我写了这个代码,通过所有素数并打印出来。

class Primes:

  def __contains__(self, num):
    for divd in range(2, num):
      if num % divd == 0:
        return False
    return True

  def __iter__(self):
    yield 2
    count = 3
    while True:
      if count in self:
        yield count
      count += 2

primes = Primes()
for x in primes:
  print(x)

它工作正常,但是我不得不创建一个Primes对象以便迭代它。如果倒数第二行是for x in Primes:而另一行是if count in Primes会更有意义,但添加@classmethod或@staticmethod装饰器会给我一个argument of type 'classobj' is not iterable错误。实际的方法是什么?

1 个答案:

答案 0 :(得分:4)

Python looks up special methods on the type of the object。要迭代一个类,您必须将__iter__方法放在元类上。

只需在for循环中创建实例:

for x in Primes():

因为创建一个元类只是为了产生素数就是太多的间接性。它看起来像这样:

class PrimesMeta(type):
    def __contains__(self, num):
        # more efficient prime number test
        if num % 2 == 0:  # even
            return False
        for divd in range(3, int(num ** 0.5) + 1, 2):
            if num % divd == 0:
                return False
        return True

    def __iter__(self):
        yield 2
        count = 3
        while True:
            if count in self:
                yield count
            count += 2

class Primes(metaclass=PrimesMeta):
    pass

对于Python 2,您可以使用:

创建Primes
class Primes(object):
    __metaclass__ = PrimesMeta

代替。

您可以使用筛子进一步改进发电机;请参阅http://code.activestate.com/recipes/117119/以获得出色的无限生成器实现。