测试某个值是否不是由迭代器产生的
Testing if some value is not produced by an iterator
我想测试某个值是否属于使用迭代器生成的数字序列。当然当值和属于序列时,一满足就可以停止。但是当它 没有 时,我想这就是问题出现的时候。
但是可以使用附加信息(例如,序列在增加)。
考虑斐波那契示例:
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
...
永不终止。但是通过观察 8
之后出现 13
,可以很容易地确定 10
不在序列中,并且由于序列在增加,因此必然 not 10 in fib
.
在 Python 中是否有一个很好的方法来实现 in
的这种行为,以便 10 in fib
终止?
简单的解决方案是实现一个 __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:
# 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)
我想测试某个值是否属于使用迭代器生成的数字序列。当然当值和属于序列时,一满足就可以停止。但是当它 没有 时,我想这就是问题出现的时候。
但是可以使用附加信息(例如,序列在增加)。
考虑斐波那契示例:
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
...
永不终止。但是通过观察 8
之后出现 13
,可以很容易地确定 10
不在序列中,并且由于序列在增加,因此必然 not 10 in fib
.
在 Python 中是否有一个很好的方法来实现 in
的这种行为,以便 10 in fib
终止?
简单的解决方案是实现一个 __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:
# 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)