Is it possible to implement a Python for range loop without an iterator variable?

匿名 (未验证) 提交于 2019-12-03 02:08:02

问题:

Is it possible to do following without the i?

for i in range(some_number):     # do something 

If you just want to do something N amount of times and don't need the iterator.

回答1:

Off the top of my head, no.

I think the best you could do is something like this:

def loop(f,n):     for i in xrange(n): f()  loop(lambda: , 5) 

But I think you can just live with the extra i variable.

Here is the option to use the _ variable, which in reality, is just another variable.

for _ in range(n):     do_something() 

Note that _ is assigned the last result that returned in an interactive python session:

>>> 1+2 3 >>> _ 3 

For this reason, I would not use it in this manner. I am unaware of any idiom as mentioned by Ryan. It can mess up your interpreter.

>>> for _ in xrange(10): pass ... >>> _ 9 >>> 1+2 3 >>> _ 9 

And according to python grammar, it is an acceptable variable name:

identifier ::= (letter|"_") (letter | digit | "_")*



回答2:

You may be looking for

for _ in itertools.repeat(None, times): ... 

this is THE fastest way to iterate times times in Python.



回答3:

The general idiom for assigning to a value that isn't used is to name it _.

for _ in range(times):     do_stuff() 


回答4:

What everyone suggesting you to use _ isn't saying is that _ is frequently used as a shortcut to one of the gettext functions, so if you want your software to be available in more than one language then you're best off avoiding using it for other purposes.

import gettext gettext.bindtextdomain('myapplication', '/path/to/my/language/directory') gettext.textdomain('myapplication') _ = gettext.gettext # ... print _('This is a translatable string.') 


回答5:

Here's a random idea that utilizes (abuses?) the data model.

class Counter(object):   def __init__(self, val):     self.val = val    def __nonzero__(self):     self.val -= 1     return self.val >= 0  x = Counter(5) while x:   # Do something   pass 

I wonder if there is something like this in the standard libraries?



回答6:

You can use _11 (or any number or another invalid identifier) to prevent name-colision with gettext. Any time you use underscore + invalid identifier you get a dummy name that can be used in for loop.



回答7:

May be answer would depend on what problem you have with using iterator? may be use

i = 100 while i:     print i     i-=1 

or

def loop(N, doSomething):     if not N:         return     print doSomething(N)     loop(N-1, doSomething)  loop(100, lambda a:a) 

but frankly i see no point in using such approaches



回答8:

t=0     for _ in range (0, 10):   print t   t = t+1 

OUTPUT:
0 1 2 3 4 5 6 7 9



回答9:

I generally agree with solutions given above. Namely with:

  1. Using underscore in for-loop (2 and more lines)
  2. Defining a normal while counter (3 and more lines)
  3. Declaring a custom class with __nonzero__ implementation (many more lines)

If one is to define an object as in #3 I would recommend implementing protocol for with keyword or apply contextlib.

Further I propose yet another solution. It is a 3 liner and is not of supreme elegance, but it uses itertools package and thus might be of an interest.

from itertools import (chain, repeat)  times = chain(repeat(True, 2), repeat(False)) while next(times):     print 'do stuff!' 

In these example 2 is the number of times to iterate the loop. chain is wrapping two repeat iterators, the first being limited but the second is infinite. Remember that these are true iterator objects, hence they do not require infinite memory. Obviously this is much slower then solution #1. Unless written as a part of a function it might require a clean up for times variable.



回答10:

Instead of an unneeded counter, now you have an unneeded list. Best solution is to use a variable that starts with "_", that tells syntax checkers that you are aware you are not using the variable.

x = range(5) while len(x) > 0:   x.pop()   print "Work!" 


回答11:

We have had some fun with the following, interesting to share so:

class RepeatFunction:     def __init__(self,n=1): self.n = n     def __call__(self,Func):         for i in xrange(self.n):             Func()         return Func   #----usage k = 0  @RepeatFunction(7)                       #decorator for repeating function def Job():     global k     print k     k += 1  print '---------' Job() 

Results:

0 1 2 3 4 5 6 --------- 7 


回答12:

If do_something is a simple function or can be wrapped in one, a simple map() can do_something range(some_number) times:

map(do_something, range(some_number)) 

If you want to pass arguments to do_something, you may also find the itertools repeatfunc recipe reads well:

To pass the same arguments:

import itertools args = [..., my args here, ...] itertools.starmap(do_something, itertools.repeat(args, some_number))  

To pass different arguments:

import itertools argses = [[1, 2], [3, 4], ...] itertools.starmap(do_something, argses)  


回答13:

#Return first n items of the iterable as a list list(itertools.islice(iterable, n)) 

Taken from http://docs.python.org/2/library/itertools.html



回答14:

If you really want to avoid putting something with a name (either an iteration variable as in the OP, or unwanted list or unwanted generator returning true the wanted amount of time) you could do it if you really wanted:

for type('', (), {}).x in range(somenumber):     dosomething() 

The trick that's used is to create an anonymous class type('', (), {}) which results in a class with empty name, but NB that it is not inserted in the local or global namespace (even if a nonempty name was supplied). Then you use a member of that class as iteration variable which is unreachable since the class it's a member of is unreachable.



回答15:

According to what Alex Martelli said. It is not true that itertools.repeat() is faster than range.

I've run several times a generation of random numbers in for loop using both methods of iteration. Basically in repeats up to 100 000 times range is faster than itertools.repeat(). But when it comes to repeat over 100 000 times it is itertools.repeat() which is faster than range.

10000 times Itertools: 0.015010 Range: 0.008006`  100000 times Itertools: 0.091061 Range: 0.087057  1000000 Itertools: 0.846565 Range: 0.911609 

I have been generating tuples of random integers in a list. Regards Marek



回答16:

What about:

while range(some_number):     #do something 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!