As title. I mean, you can invoke next(obj) and point to the next element. So the internal state of the iterable or generator will change.
Why they are hashable?
As title. I mean, you can invoke next(obj) and point to the next element. So the internal state of the iterable or generator will change.
Why they are hashable?
The general rule for hashing objects is:
__eq__ is overridden, object equality is defined by identity, and hashing matches__eq__ is overridden, and __hash__ is not, then hashing is blocked by default (because mutability that effects the result of an equality check would break the hash invariants); re-enabling hashing requires implementing __hash__, which implicitly says "My equality and hash semantics are stable/consistent over time", but doesn't require that things not tied to equality or the hash code be stable.Point is, the condition for hashability isn't immutability, it's consistency with equality (and implied stability of both equality and hash). Since most iterators and all generators don't implement __eq__ (there is no meaningful way to implement it without running out the iterator and losing the information you just used to compare it), it's all based on identity, just like with any user-defined object that doesn't define equality.
While the internal state of the generator can change, the generator as a whole can never add something to itself, and can never go back a step while iterating over it. Therefore, a generator is a fixed immutable object, which is almost the definition of being hashable.
But even more deeply than that, even mutable objects can be hashable as long as they define __hash__ as an instance method, but that is rarely desireable for mutable objects.