Posts: 1
Threads: 1
Joined: Dec 2025
Hi All,
First time poster so please excuse noob mistakes.
I am using Micropython to program a microcontroller (an ESP32 for this project) and one of the things I need to do is iterate through a list of fixed values repeatedly, that is restart at the first item after the last item has been returned. My knowledge of Python is not deep, it's pretty basic so I'm currently doing this.
chan_order = (5, 9, 2, 14, 3, 7, 13, 6, 12, 4, 8, 11, 1, 10)
n = 0
next_chan = 5
def cb(t):
global n
n = (n + 1) % 14
next_chan = chan_order[n]
do something with next_chan
...Function cb is a callback routine driven by a timer, so it's run continuously, 100 times a second.
This works, but in my quest to learn more about Python I started exploring the murky world of iterators and generators, as it seemed to me that I could then just do something like "next_chan = somefunc.next()", but the stumbling block I keep tripping over is getting the iterator to restart at the beginning when it hits the last item in the list. I found in Python there is a library called "itertools", which has a "cycle" function in it that looks like it would do what I want to do, but unfortunately itertools doesn't exist in Micropython.
Is there a way I can use an iterator (or a generator) to do this? Or is it overcomplicating the solution.
All advice gratefully received.
Posts: 1,301
Threads: 151
Joined: Jul 2017
Dec-04-2025, 07:42 AM
(This post was last modified: Dec-04-2025, 07:42 AM by Pedroski55.)
Well, I think you don't need generators for small amounts of data.
I think for your purpose, lists or tuples are most suited
Here a link to the docs for Python lists
# tuples are immutable, theoretically
chan_order = (5, 9, 2, 14, 3, 7, 13, 6, 12, 4, 8, 11, 1, 10)
type(chan_order) # <class 'tuple'>
for c in chan_order:
print(c)
# generators are used up then stop
chan_gen = (x for x in chan_order)
type(chan_gen) # <class 'generator'>
# see the numbers
for g in chan_gen:
print(g)
# try that again, get nothing
for g in chan_gen:
print(g)
# list is most useful, can be changed, can't be used up
chan_list = list(chan_order) # or do it like this: chan_list = [x for x in chan_order]
chan_list # [5, 9, 2, 14, 3, 7, 13, 6, 12, 4, 8, 11, 1, 10]
type(chan_list) # <class 'list'>
chan_range = range(1,15)
type(chan_range) # <class 'range'>
for i in chan_range:
print(i)Info:
Quote:There are four collection data types in the Python programming language:
List is a collection which is ordered and changeable. Allows duplicate members.
Tuple is a collection which is ordered and unchangeable. Allows duplicate members.
Set is a collection which is unordered, unchangeable*, and unindexed. No duplicate members.
Dictionary is a collection which is ordered** and changeable. No duplicate members.
A dictionary has key: value pairs. A dictionary can have duplicate values, but not duplicate keys.
Posts: 4,904
Threads: 79
Joined: Jan 2018
Dec-04-2025, 07:45 AM
(This post was last modified: Dec-04-2025, 07:50 AM by Gribouillis.)
Hi and welcome to python-forum.io!
I don't know which features micropython lacks, but you could try this
chan_order = (5, 9, 2, 14, 3, 7, 13, 6, 12, 4, 8, 11, 1, 10)
def cycle_tuple(t: tuple):
while t:
for c in t:
yield c
chan_cycle = cycle_tuple(chan_order)
if __name__ == "__main__":
for i in range(30):
c = next(chan_cycle)
print(c, end=" ")
print()My output:
Output: 5 9 2 14 3 7 13 6 12 4 8 11 1 10 5 9 2 14 3 7 13 6 12 4 8 11 1 10 5 9
« We can solve any problem by introducing an extra level of indirection »
Posts: 232
Threads: 0
Joined: Jun 2019
Hi,
if you take a look in the docs of CPython for the itertools module, you will find code which does roughly the same like itertools.cycle, implemented with the core functionality of Python only: https://docs.python.org/3/library/iterto...ools.cycle
Regards, noisefloor
bowlofred likes this post
Posts: 1,301
Threads: 151
Joined: Jul 2017
@ Gribouillis
You are the expert here, not me, but don't you think an endless while loop is, well, not recommended?
Posts: 6,981
Threads: 22
Joined: Feb 2020
The OP has is a sequence that repeats endlessly.
Posts: 1,301
Threads: 151
Joined: Jul 2017
Well, I just think, if the OP wants to log some data which occurs 100 times a second, the log file will get quite big quite quickly.
There must be a STOP condition, n'est pas?
Posts: 4,904
Threads: 79
Joined: Jan 2018
Dec-05-2025, 10:43 AM
(This post was last modified: Dec-05-2025, 10:43 AM by Gribouillis.)
(Dec-05-2025, 08:35 AM)Pedroski55 Wrote: Well, I just think, if the OP wants to log some data which occurs 100 times a second, the log file will get quite big quite quickly.
There must be a STOP condition, n'est pas? The while loop inside the generator function does not need a stop condition because it is stopped every time by the yield statement. The loop is driven by the client code which determines how many times it calls the next() function. Every external call to next(chan_cycle) runs the internal loop once. The client code has all the responsibility.
A nice feature of generator objects is that they allow us to work conceptually with infinite sequences, although every execution of the program will consume only a finite number of elements.
« We can solve any problem by introducing an extra level of indirection »
Posts: 232
Threads: 0
Joined: Jun 2019
(Dec-05-2025, 08:35 AM)Pedroski55 Wrote: There must be a STOP condition, n'est pas? No, there must be no stop condition. At least not for the TS, as the question is about an endless generator. Seems to be useful for him / her. There can be a stop condition, but it is neither mandatory nor enforced by Python. Remember that an endless generator is technically _not_ the same like an infinite loop.
Regards, noisefloor
Posts: 5
Threads: 0
Joined: Nov 2025
This is probably what you're looking for:
chan_order = (5, 9, 2, 14, 3, 7, 13, 6, 12, 4, 8, 11, 1, 10)
def chan_cycle():
while True:
for ch in chan_order:
yield ch
chan_iter = chan_cycle()Then in your callback:
def cb(t):
next_chan = next(chan_iter)
# do something with next_chanThat's it.
When it hits the end of the tuple, it just starts again automatically.
|