-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Iterable vs Iterator distinction #2942
Comments
I think no, since it reflects the Python runtime semantics. Your code correctly passes mypy because it works at runtime without errors. The problem with your code is a design/behavior error, not a type error: generator expression is already exhausted before the for loop. Your code implies that you need an "immutable" iterable. So that you could wrapt the argument in a tuple initially |
We are not going to change this, but you can use the type Container for iterables that can be iterated repeatedly. |
@gvanrossum You meant @ilevkivskyi I also thought it's difficult, but it appears this problem has recently been solved in 3.6 with the addition of
Now an attempt to call |
Yeah, sorry, I meant Collection. :-)
…--Guido (mobile)
On Mar 2, 2017 5:38 PM, "pkch" ***@***.***> wrote:
@gvanrossum <https://github.com/gvanrossum> You meant Collection, not
Container; Container would cause mypy to reject the function as
implemented because Container doesn't guarantee the presence of __iter__,
which is implicitly used inside the function.
@ilevkivskyi <https://github.com/ilevkivskyi> I also thought it's
difficult, but it appears this problem has recently been solved.
Collection works perfectly:
from typing import Collection
def count_max_values(iterable: Collection) -> int:
"""Count the number of times the maximum value appears in iterable"""
max_value = max(iterable, default=None)
counter = 0
for item in iterable:
if item == max_value:
counter += 1
return counter
Now an attempt to call count_max_values( (i for i in range(5)) ) will be
statically rejected by mypy.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2942 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ACwrMuXIT0wqU-nE5FggOy0RLoBD1Hljks5rh28rgaJpZM4MQ0qZ>
.
|
I think many python programmers think of an iterable as a container of items that allows several passes through it. In other words, they would think the following code is correct:
Obviously, if the argument was an
Iterator
, there would be no doubt that the above implementation is incorrect.However, at the moment, the following code would pass the type check:
The reason is that the definition of
Iterable
is currently only concerned with the presence of__get_item__()
or__iter__()
methods, and so everyIterator
is automatically anIterable
.Would it be worth redefining
Iterator
andIterable
? For example, the rule could be that if an object defines both__iter__
and__next__
methods, it is not anIterable
(since it's very weird for an iterable to have a__next__
method); otherwise, if it defines__iter__
or__getitem__
, it is anIterable
. If necessary, an option could be given to the programmer to explicitly override this rule (marking asIterable
an object with both__iter__
and__next__
; or as notIterable
an object with__iter__
and without__next__
).The text was updated successfully, but these errors were encountered: