Dan*_*aga 6 python iterator generator
考虑下面的虚拟示例:
def common_divisors_generator(n, m):
# Init code
factors_n = [i for i in range(1, n + 1) if n%i == 0]
factors_m = [i for i in range(1, m + 1) if m%i == 0]
# Iterative code
for fn in factors_n:
for fm in factors_m:
if fn == fm:
yield fn
# The next line is fast because no code is executed yet
cdg = common_divisors_generator(1537745, 373625435)
# Next line is slow because init code is executed on first iteration call
for g in cdg:
print(g)
Run Code Online (Sandbox Code Playgroud)
一旦生成器第一次被迭代(与生成器初始化时相反),就会执行花费很长时间来计算的初始化代码。我希望在生成器初始化时执行它的init代码。
为此,我将生成器转换为迭代器类,如下所示:
class CommonDivisorsIterator(object):
def __init__(self, n, m):
# Init code
self.factors_n = [i for i in range(1, n + 1) if n%i == 0]
self.factors_m = [i for i in range(1, m + 1) if m%i == 0]
def __iter__(self):
return self
def __next__(self):
# Some Pythonic implementation of the iterative code above
# ...
return next_common_divisor
Run Code Online (Sandbox Code Playgroud)
__next__与生成器中带有yield关键字的迭代代码的简单性相比,我能想到的实现上述方法的所有方式都非常麻烦。
__next__在迭代器类中实现该方法的最Pythonic方式是什么?
或者,如何修改生成器,以便在初始化时执行初始化代码?
在两种情况下(无论使用函数还是类),解决方案都是将实现分为两个函数:设置函数和生成器函数。
yield在函数中使用会将其转换为生成器函数,这意味着它在被调用时会返回生成器。但是,即使不使用yield,也不会阻止您创建生成器并返回它,就像这样:
def common_divisors_generator(n, m):
factors_n = [i for i in range(1, n + 1) if n%i == 0]
factors_m = [i for i in range(1, m + 1) if m%i == 0]
def gen():
for fn in factors_n:
for fm in factors_m:
if fn == fm:
yield fn
return gen()
Run Code Online (Sandbox Code Playgroud)
而且,如果您使用的是类,则无需实现__next__方法。您可以yield在__iter__方法中使用:
class CommonDivisorsIterator(object):
def __init__(self, n, m):
self.factors_n = [i for i in range(1, n + 1) if n%i == 0]
self.factors_m = [i for i in range(1, m + 1) if m%i == 0]
def __iter__(self):
for fn in self.factors_n:
for fm in self.factors_m:
if fn == fm:
yield fn
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
649 次 |
| 最近记录: |