测试迭代器是否产生某些值

时间:2017-07-08 12:47:01

标签: python iterator sequence fibonacci iterable

我想测试某个值是否属于使用迭代器生成的数字序列。当然,当值 属于序列时,可以在满足该值时立即停止。但当它时,我想这就是问题出现的时候。

然而,可以使用附加信息(例如,序列正在增加)。

考虑斐波那契的例子:

class FibonacciIterator(object):
    def __init__(self):
        self.mem = [0, 1]
    def __next__(self):
        curr = self.mem[0]
        new = self.mem[0]+self.mem[1]
        self.mem[0] = self.mem[1]
        self.mem[1] = new
        return curr

class Fibonacci(object):
    def __iter__(self):
       return FibonacciIterator()

如果有人测试8是否属于序列,那么一切都很好:

>>> fib = Fibonacci()
>>> 8 in fib
True

但是,如果一个测试10(不属于序列)那么

>>> 10 in fib
...

永远不会终止。但是,可以通过在10到达8之后观察13并且因为序列正在增加然后not 10 in fib来轻松确定in不在序列中。

在Python中有没有很好的方法来实现10 in fib的这种行为,以便var collapsed: Bool { didSet { view.setNeedsUpdateConstraints() } } @IBAction func onButtonClick(sender: UISwitch) { view.layoutIfNeeded() collapsed = !collapsed UIView.animate(withDuration: 0.3) { view.layoutIfNeeded() } } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) view.setNeedsUpdateConstraints() } override func updateViewConstraints() { constraint1.isActive = !collapsed constraint2.isActive = collapsed super.updateViewConstraints() } 终止?

1 个答案:

答案 0 :(得分:1)

简单的解决方案是实现一个只迭代迭代器副本的__contains__方法:

class FibonacciIterator(object):
    def __init__(self):
        self.mem = [0, 1]

    def __iter__(self):
        return self

    def __contains__(self, value):
        testit = FibonacciIterator()
        testit.mem = list(self.mem)  # copy
        for item in testit:
            if item == value:
                return True
            if item > value:
                return False

    def __next__(self):
        curr = self.mem[0]
        self.mem = self.mem[1], sum(self.mem)
        return curr

class Fibonacci(object):
    def __iter__(self):
        return FibonacciIterator()

    def __contains__(self, value):
        return value in iter(self)

然而,还有另一种方法可以确定数字是否是斐波纳契数:如果(5*n**2 + 4)(5*n**2 – 4)或两者都是完美的正方形(整数的平方)。

我将使用this answer中的方法来实现is_square函数:

def is_square(apositiveint):
    # Source: https://stackoverflow.com/a/2489519/5393381
    # Credit: Alex Martelli

    x = apositiveint // 2
    seen = {x}
    while x * x != apositiveint:
        x = (x + (apositiveint // x)) // 2
        if x in seen: 
            return False
        seen.add(x)
    return True

class FibonacciIterator(object):
    def __init__(self):
        self.mem = [0, 1]

    def __iter__(self):
        return self

    def __contains__(self, value):
        if value < self.mem[0]:
            return False
        else:
            # Just check if at least one of both is a perfect square
            value_squared_times_five = 5*value**2
            return is_square(value_squared_times_five + 4) or is_square(value_squared_times_five - 4)

    def __next__(self):
        curr = self.mem[0]
        self.mem = self.mem[1], sum(self.mem)
        return curr

class Fibonacci(object):
    def __iter__(self):
        return FibonacciIterator()

    def __contains__(self, value):
        return value in iter(self)