Page 1 of 1
Is built-in function iter only partially implemented?
Posted: Sun Oct 17, 2021 12:41 pm
by snake77
Code: Select all
Python 3.9.2 (default, Feb 28 2021, 17:03:44)
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> iter(int, 1)
<callable_iterator object at 0x7f2623b7c100>
>>>
vs.
Code: Select all
MicroPython v1.17-80-g4c9e17e0a-dirty on 2021-10-14; linux version
Use Ctrl-D to exit, Ctrl-E for paste mode
>>> iter(int, 1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: function takes 1 positional arguments but 2 were given
>>>
Re: Is built-in function iter only partially implemented?
Posted: Mon Oct 18, 2021 1:08 am
by mattyt
That's correct, the
sentinel is not implemented. (The note mentioned next but it's the same reasoning for iter.)
Re: Is built-in function iter only partially implemented?
Posted: Mon Oct 18, 2021 6:06 am
by stijn
Second argument for next is implemented in the code depending on compilation flags though, which isn't the case for iter
Re: Is built-in function iter only partially implemented?
Posted: Mon Oct 18, 2021 9:54 pm
by snake77
Well, for the second argument for next there is a very easy obvious workaround with try ... except StopIteration. Am I overlooking the easy workaround for the missing second argument of iter?
Re: Is built-in function iter only partially implemented?
Posted: Tue Oct 19, 2021 6:47 am
by stijn
The 2-argument version does something completely different so indeed no easy workaround. I think it should be possible to implement it yourself, then override the built-in iter to call your version insead.
Re: Is built-in function iter only partially implemented?
Posted: Tue Oct 19, 2021 7:39 am
by stijn
I got curious so here's the (briefly tested) exercise:
Code: Select all
import builtins
class IterateCallable:
def __init__(self, func, sentinel):
self.func = func
self.sentinel = sentinel
def __iter__(self):
return self
def __next__(self):
if (r := self.func()) == self.sentinel:
raise StopIteration
return r
orig_iter = builtins.iter
def iter2(obj, *args):
if not args:
return orig_iter(obj)
return IterateCallable(obj, *args)
builtins.iter = iter2
def GetFunc():
i = 0
def Func():
nonlocal i
i += 1
return i
return Func
for p in iter([1, 2]):
print(p)
for p in iter(GetFunc(), 3):
print(p)
Re: Is built-in function iter only partially implemented?
Posted: Wed Oct 20, 2021 1:14 am
by mattyt
Sorry, there's much better information in issue
#5384 (I wasn't aware of this ticket when I first responded).
The summary is that yes, it's not implemented. The two argument form isn't so common and there is a work-around (documented in the issue) so I guess it seemed like a reasonable candidate to omit.
It
could be added if there's a strong enough case to do so, though it will probably need to be hidden behind a compile-time option (like next) to reduce the impact on micros with fewer resources.
Please comment in the issue if you have strong opinions!