6 ms·
It's a great idea if you want to make small callable objects with limited (hidden) state, in a way that's easy to translate between any languages which support
by andreyf 17y ago
It's a great idea if you want to make small callable objects with limited (hidden) state, in a way that's easy to translate between any languages which support closures. For example, in JS:
function gencycle() {
var args = Array.prototype.slice.apply(arguments),
i = 0;
return function cycle() {
i = (i+1) % args.length;
return args[i];
}
}
I can then use gencycle("red", "green", "blue") when I want a function which gives me a rotation of colors.
In py26, I'd write it as:
class GenCycle(object):
def __init__(self, *args):
super(GenCycle, self).__init__()
self.args = args
self.i = 0
def __call__(self):
self.i = (self.i+1) % len(self.args)
return self.args[self.i]
In Python 3, I'd have to choose between the two versions.
- j_baker 17y ago>>> from itertools import cycle >>> iter = cycle(['red', 'green', 'blue']) >>> iter.next() 'red' >>> iter.next() 'green' >>> iter.next() 'blue' >>> iter.next() 'red'
- jmillikin 17y agoI believe he's using cycle() as a simple example, to illustrate a more complex requirement.
- jmillikin 17y agoThe preferred way to do that in Python is as a co-routine (AKA generator). Besides being easier to read and reason about, generators implement common protocols, such as the iteration protocol. This means you can use generators in for-loops, as a parameter to list(), or anywhere else that accepts an iterator. Here's an example of cycle() as a co-routine: def cycle(*args): i = 0 while True: i = (i + 1) % len (args) yield args[i] for arg in cycle("red", "green", "blue"): print (arg) Alternatively, if you really want to use a callable: gencycle = lambda *args: cycle(*args).next get_next = gencycle("red", "green", "blue") print (get_next()) print (get_next()) print (get_next()) Either way, it'll be cleaner than an explicitly stateful object.