Python's secret second argument to iter()

preview_player
Показать описание
Iter can take TWO args, lets take a look.

Did you know that Python's iter() builtin can actually take TWO arguments? This is a very obscure feature of Python. In this video we see how it differs from the very common single-argument form of iter(), how to use it, and what a better alternative is.

SUPPORT ME ⭐
---------------------------------------------------

Top patrons and donors: Jameson, Laura M, Vahnekie, Dragos C, Matt R, Casey G, Johan A, John Martin, Jason F, Mutual Information, Neel R

BE ACTIVE IN MY COMMUNITY 😄
---------------------------------------------------

CHAPTERS
---------------------------------------------------
0:00 Intro
0:12 Single arg iter
1:17 Two arg iter
5:47 Walrus operator
Рекомендации по теме
Комментарии
Автор

I don't think I've ever used iter(), just __iter__ and a for-loop like you mentioned. interesting tidbit. Promise I'll never use this in real code lol

tassaron
Автор

Although I have never used `iter()` before, this video is interesting to me.
Can I suggest you to make videos about __init__.py and __all__? While I (think that I) understand what are they for, I am not sure how to use them in practice. It would be great if you can share your tips and insights about them. Thank you.

NicolasChanCSY
Автор

The second argument of iter seems like something I would have made in my earlier days of python, abusing the dynamic typing. I have long learned that just because you can doesn't mean you should, and having consistent behavior regardless of the inputs should be the goal. I agree this would fit better in itertools, and it seems weird that it even made its way into iter() in the first place. I will continue not using the second argument, but interesting tidbit nevertheless.

UnFallenRain
Автор

Love your videos! If i have a stressful day and a video of yours comes up. Ill stop having stress and just enjoy watching your video. Your voice, your style, your choice of topics and ofc you as a whole just make my day. Your videos are so calming and yet super informative. Most of my deep understanding of python was gathered watching your videos.

I just want to thank you!

I always share your channel to any1 interested in python!

nathanoy_
Автор

A typical use case which comes to mind for iter(callable, sentinel) is with a queue which holds a lot of tasks and from which N threads read until they read a specific end-token (a sentinel, e.g. None or Ellipsis or a similar special value). I.e. for task in iter(q.get, None): … . The feeder of the queue who starts the N threads will also put N sentinel values into the queue, that’s it. Each thread will terminate automatically after reading one of the sentinel values.

alfeberlin
Автор

There's something I don't quite understand. Why not rename '__call__()' to 'read_chunk(self)' (without arguments) and then use iter(reader.read_chunk, b' ')? You only need to use partial if you want to have additional arguments in read_chunk(), but if you define the class instance reader beforehand then you can simply put that argument in the constructor.

Am I missing something?

QuantumHistorian
Автор

I could see some utility in the two-argument form for consuming a cursor in SQL operations. That said, it's just as easy to write a __iter__ on a wrapper class, and even a __enter__ and __exit__ for making IO self-managing, but if you're trying to write as little code as possible, such a function could make sense.

I agree that it's odd, and unintuitive, to completely rewrite the expected first arg type to support a seemingly niche operation.

penguindrummaster
Автор

my one use case for 2 argument iter: sometimes i want a simple infinite iterator to feed into map or a generator expression, and iter(int, 1) is very useful for that. int() always returns 0, so it will never hit the sentinel

aragonnetje
Автор

every time I used this feature has been just to see how the code would turn out if I did so and it always ended up being a longer and harder to read line... the walrus operator makes for such a better alternative! I was hoping to see you mention it in this video and tbh i’m quite glad you did!

apenasmeucanal
Автор

Although I agree that the name overloading isn't great, I actually find the two arg form relatively useful when I have a method that steps through some data, eventually returning a sentinel. It's very convenient to convert this easily into an iterable. You don't need a dunder call, just using a bound method like iter(foo.read, ``) works great.

dalehagglund
Автор

Usually the reason I'd call the `iter` builtin is for the idiom `next(iter(thing))`, which I use to pick the element of a possibly-empty singleton iterator or container, while imposing only the bare minimum requirement on what type `thing` actually is -- and in particular not requiring that it support `len(thing)` or some sort of `thing[0]`. It also feels nice being able to uniformly handle all possible "empty" cases in the same `except StopIteration` clause.

AJMansfield
Автор

I don't have anything specific to mention about the video, amazing content as always. This channel is the perfect way how an educational / programming channel should work.

You assume perfectly reasonable prerequisite for the topic and get right to it with no over simplication or "just trust me for now". Gives a great perspective of of programming language and style works inside and out.

Great content, change nothing in the style.

You should try to do more non python videos if your YouTube schedule allows it since it's a bit more fun (for me) to learn more about working of compiled languages.

ShrirajHegde
Автор

Mista MurphyCoding be the only mans out here who explains intermediate concepts to us in a way that feels like we are absolute beginners again. Truly a special skill that I wish was more commonplace.

Can't thank you enough for the content you produce!

Hobolover
Автор

hi James, can you do a video on how to create a proper package of a codebase in Python? There are many articles in the web but nothing that gives a complete understanding with the latest/best methods. Would be great if you can mention the minimum Python version required to do it also.

aadithyavarma
Автор

I didn't even know, you could do this.
But now I think there might actually be some use for it:

1. You could just pass a method instead of implementing __ call__

iter(ChunkedReader(f, 4).read_chunk, b'')

(This is kinda similar to your "partial" example of course)

2. You can also do this:

iter(iter(someObject).__next__, sentinel)

This still looks kinda weird but might actually be somewhat reasonable to have as a feature

danielderwertvolle
Автор

Assignment operator is awesome, I've always been missing this C-like piece in Python specifically for the while loop condition use case!

antonsubbotin
Автор

Would be useful for a function with a closure like the fib defined as
def fib():
a, b = 0, 1
def inner():
nonlocal a, b
ret, a, b = a, b, b+a
return ret
return inner

bzboii
Автор

Funny I just saw this today, I actually came up with the following for a Leetcode problem the other day. Probably wouldn't do anything like this in production code, but this 2 argument form of iter saved an extra explicit loop.
def str) -> int:
def window_lens():
window = set()
start = iter(text)
for end in text:
if end in window:
window -= set(iter(start.__next__, end))
else:
window.add(end)
yield len(window)

return max(window_lens())

grantpeterson
Автор

I think the obvious use case for this is a simple way to wait for a condition that's not necessarily influenced by your code, like watching for a specific file to exist or something. Or at least, it would be if iter wasn't the keyword for it - way more readable to just use a while-pass.

Also, I find it funny that you consider the walrus operator to be a better alternative since AFAIK a lot of people don't like that that exists either.

SirVer
Автор

4:39 you could use item.read_chunk as your function and that works since methods are callables that change can internal state

MrRyanroberson