Python有一种在for
循环中自动生成计数器变量的优雅方式:enumerate
函数。这节省了初始化和递增计数器变量的需要。计数器变量也很难看,因为它们在循环完成后通常是无用的,但它们的范围不是循环的范围,因此它们不需要占用命名空间(尽管我不确定enumerate
是否实际解决了这个问题)
我的问题是,while
循环是否存在类似的pythonic解决方案。由于enumerate
返回迭代器,while
将不适用于enumerate
循环。理想情况下,解决方案应该是“pythonic”,不需要函数定义。
例如:
x=0
c=0
while x<10:
x=int(raw_input())
print x,c
c+=1
在这种情况下,我们希望避免初始化和递增c
。
澄清:
这可以通过手动终止的无限for
循环来完成,正如一些人所建议的那样,但我正在寻找一种能让代码更清晰的解决方案,我认为这个解决方案不会让代码更清晰这种情况。
答案 0 :(得分:7)
Ignacio的答案改进(可读性,我会说):
x = 0
for c in itertools.takewhile(lambda c: x < 10, itertools.count()):
x = int(raw_input())
print x, c
优点:
答案 1 :(得分:6)
再次使用itertools
...
import itertools
for c, x in enumerate(
itertools.takewhile(lambda v: v < 10,
(int(raw_input()) for z in itertools.count())
)
):
print c, x
答案 2 :(得分:2)
如果您想在while
循环之前初始化零,则可以将Singleton与计数器一起使用:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(
cls, *args, **kwargs)
cls.count=0
else:
cls.count+=1
return cls._instance
然后只有一个Singleton实例,每个附加实例只添加一个:
>>> Singleton().count # initial instance
0
>>> Singleton().count
1
>>> Singleton().count
2
>>> Singleton().count
3
然后你的while循环变为:
while Singleton():
x=int(raw_input('x: '))
if x>10: break
print 'While loop executed',Singleton().count,'times'
输入1,2,3,11
打印:
x: 1
x: 2
x: 3
x: 11
While loop executed 4 times
如果您不介意在while
循环之前进行单行初始化,则可以只对子函数进行子类化:
import collections
class WhileEnum(collections.Iterator):
def __init__(self,stop=None):
self.stop=stop
self.count=0
def next(self): # '__next__' on Py 3, 'next' on Py 2
if self.stop is not None:
self.remaining=self.stop-self.count
if self.count>=self.stop: return False
self.count+=1
return True
def __call__(self):
return self.next()
然后你的while循环变为:
enu=WhileEnum()
while enu():
i=int(raw_input('x: '))
if i>10: break
print enu.count
我认为第二种方法是更好的方法。您可以拥有多个枚举器,还可以设置限制循环次数:
limited_enum=WhileEnum(5)
答案 3 :(得分:1)
我认为不可能按照你想要的方式做你想做的事。如果我理解正确,你需要一个while
循环,每次循环增加一个计数器,而不实际暴露循环范围之外的可见计数器。我认为这样做的方法是将while
循环重写为非终止for
循环,并手动检查结束条件。对于您的示例代码:
import itertools
x = 0
for c in itertools.count():
x = int(raw_input())
print x, c
if x >= 10:
break
问题在于,从根本上说,你正在使用计数器进行迭代。如果您不想公开该计数器,则需要来自循环结构。在没有定义新功能的情况下,您会遇到标准循环和显式检查。
另一方面,你也可以为此定义一个生成器。你仍然在迭代,但你至少可以将检查包装在循环结构中。