Issue 5032: itertools.count step - Python tracker (original) (raw)
Issue5032
Created on 2009-01-22 13:14 by steve21, last changed 2022-04-11 14:56 by admin. This issue is now closed.
Messages (13) | ||
---|---|---|
msg80368 - (view) | Author: Steve (steve21) | Date: 2009-01-22 13:14 |
I'd like to request a 'step' argument be added for itertools.count. It would be useful in the same way that step is useful for the 'range' function. ('range' and 'count' are very similar - 'count' could even be merged into 'range', for example by making 'range(None)' equivalent to 'count()') | ||
msg80384 - (view) | Author: Raymond Hettinger (rhettinger) * ![]() |
Date: 2009-01-22 21:56 |
Am not too excited about this one. As a heavy itertools user myself, I've never had occasion to need a step argument. As an implementer, I'm aware that it would make the code for count() much more complex (because of the internal optimizations and because step can be positive, negative, or zero). Have you had any real world use cases where count(start, step) would have been the best solution? | ||
msg80605 - (view) | Author: Steve (steve21) | Date: 2009-01-27 01:42 |
Here's a couple of functions I use with count and step: def cf_e(): '''return: (iterator) the infinite continued fraction for e e=[2; 1, 2, 1, 1, 4, 1, 1, 6, 1 , ... , 1, 2k, 1, ...] ''' yield 2 for k in itertools.count(2, 2): yield 1 yield k yield 1 def prime_factors(n): '''n: (int > 1) return: (list) the sorted list of tuples (p,e) of prime factors of n p is a prime factor, e is the number of times the factor is used ''' ret = [] if n <= 1: return ret # factors: use known (small) primes, then possible primes (odd numbers) for factor in itertools.chain([2,3,5,7,11], itertools.count(13, 2)): if factor*factor > n: if n != 1: ret += [(n, 1)] break for e in itertools.count(0): div, mod = divmod(n, factor) if mod != 0: break n = div if e >= 1: ret += [(factor, e)] return ret | ||
msg80609 - (view) | Author: David W. Lambert (LambertDW) | Date: 2009-01-27 02:48 |
Nice. Now I know that eee is a least transcendental number. But I can't figure out why inserting this code into your file (and removing some "itertools.") is difficult or unreadable. I maintain a personal library of modules that I don't actually expect Guido to include in the python standard library. import itertools def count(offset=0,stride=1): for i in itertools.count(): yield offset+i*stride # this version probably performs faster def count(offset=0,stride=1): while True: yield offset offset += stride | ||
msg80614 - (view) | Author: Steve (steve21) | Date: 2009-01-27 03:56 |
I already use the second version of the count function you give (without default arguments which I am not a big fan of). I'm not saying its difficult or unreadable to bypass itertools.count and write your own enhanced count function. But if I use a custom count function, you use a custom count function, and possibly many others too, then there could be a common requirement for a step argument and it might be a good idea too make it more widely available. Haskell has a powerful and concise list notation, some of which Python has already borrowed from: multiple3 = [3,6..] | ||
msg80618 - (view) | Author: David W. Lambert (LambertDW) | Date: 2009-01-27 04:37 |
Probably a better prime factor algorithm uses Sieve of E. to generate primes through int(1+sqrt(n)) and test these. The other algorithm uses a custom generator anyway. Oh well, good luck, I'll shut up. You do have use cases that I couldn't think of. Dave. | ||
msg80643 - (view) | Author: Raymond Hettinger (rhettinger) * ![]() |
Date: 2009-01-27 10:55 |
I've looked again at what it would take to update the C code and think that the optimizations there make it difficult to add this feature without adding a lot of code complexity and without slowing-down the common case. Also, I value the simplicity of the current API. Suggest you use "range(start, sys.maxsize, step)" or just roll your own generator (like Lambert's second version). | ||
msg81725 - (view) | Author: Raymond Hettinger (rhettinger) * ![]() |
Date: 2009-02-12 05:40 |
Found a way to do this while keeping full speed on the default case. Also, fixed an error where the start argument was rounded to the nearest integer. Also, improved the utility over its cousin, range() by allowing floating point arguments. See r69522 | ||
msg81736 - (view) | Author: Mark Dickinson (mark.dickinson) * ![]() |
Date: 2009-02-12 10:57 |
A couple of comments: > Also, improved the utility over its cousin, range() by allowing floating > point arguments. Is this wise? From a numerical perspective, it seems to me that using count with floating-point arguments is almost always going to be the wrong thing to do (unless those floats are integral), and that allowing floating-point arguments invites misuse. For example, I'd be suspicious of code that looked like: for x in count(0.0, 0.1): do_something_with_x where it seems quite likely that what's intended is the more robust: for i in count(): x = i/10.0 do_something_with_x Second (unrelated) comment: on my machine, list(count()) appears to hang, and is unresponsive to keyboard interrupts. Is there any easy way to make this interruptible? While list(count()) is clearly a stupid thing to type, it would be nice if it didn't hang the interpreter. | ||
msg81745 - (view) | Author: Raymond Hettinger (rhettinger) * ![]() |
Date: 2009-02-12 11:56 |
Not too worried about either issue. For the first, it makes the code closer to its pure python equivalent. Better to add some math module function like Matlab's linspace(). It's hard to prevent people from creating numerical mistakes no matter what. Besides, now it's possible to write: count(Decimal('1.1'), Decimal('.1')) and get exact progressions. For the second, the non-interruptability issue is everpresent throughout the language. If we get some uniform way of dealing with it, that would be great (though I expect it will slow down lots of things we care about and provide nearly zero benefit). Since count() and repeat() came out in itertools eons ago, there have been zero bug reports or user complaints about the issue. So, I'll take it as a non-issue. | ||
msg81748 - (view) | Author: Mark Dickinson (mark.dickinson) * ![]() |
Date: 2009-02-12 12:02 |
> to write: count(Decimal('1.1'), Decimal('.1')) and get exact > progressions. That's pretty cool. :-) > in itertools eons ago, there have been zero bug reports or user > complaints about the issue. So, I'll take it as a non-issue. Fair enough. | ||
msg81758 - (view) | Author: Raymond Hettinger (rhettinger) * ![]() |
Date: 2009-02-12 12:40 |
More coolness: count(Fraction(2,3), Fraction(1,6)) | ||
msg81800 - (view) | Author: David W. Lambert (LambertDW) | Date: 2009-02-12 18:47 |
I run my shells with low priority so I can sneak around and kill them. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:56:44 | admin | set | github: 49282 |
2009-02-12 18:47:56 | LambertDW | set | messages: + |
2009-02-12 12:40:33 | rhettinger | set | messages: + |
2009-02-12 12:02:18 | mark.dickinson | set | messages: + |
2009-02-12 11:56:49 | rhettinger | set | messages: + |
2009-02-12 10:57:48 | mark.dickinson | set | nosy: + mark.dickinsonmessages: + |
2009-02-12 05:42:46 | rhettinger | set | status: open -> closedresolution: accepted |
2009-02-12 05:40:41 | rhettinger | set | messages: + |
2009-01-27 10:55:49 | rhettinger | set | messages: + |
2009-01-27 04:37:53 | LambertDW | set | messages: + |
2009-01-27 03:56:59 | steve21 | set | messages: + |
2009-01-27 02:48:02 | LambertDW | set | messages: + |
2009-01-27 01:42:17 | steve21 | set | messages: + |
2009-01-23 04:36:58 | LambertDW | set | nosy: + LambertDW |
2009-01-22 21:56:03 | rhettinger | set | messages: + |
2009-01-22 18:43:00 | rhettinger | set | priority: lowassignee: rhettingernosy: + rhettingercomponents: + Extension Modules, - Noneversions: + Python 3.1, Python 2.7, - Python 3.0 |
2009-01-22 13:14:30 | steve21 | create |