如何静态覆盖 __iter__ 和 __contains__?

How to override __iter__ and __contains__ statically?

我写了这段代码,遍历所有素数并将它们打印出来。

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 错误。执行此操作的实际方法是什么?

Pythonlooks up special methods on the type of the object。要迭代 class,您必须将 __iter__ 方法放在 metaclass.

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

for x in Primes():

因为创建元class 只是为了产生素数,这太间接了。它看起来像这样:

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/ 以获得出色的无限生成器实现。