The hash value is apparently based on the identifier of the object, and not on its contents. You probably see this result because you do not store generators, so they are garbage collected and their identifiers are reused. Here are a few other examples that show this is not just one hash:
>>> x = (i for i in [0, 1, 2, 3, 4, 5, 6]) >>> y = (i for i in [0, 1, 2, 3, 4, 5, 6]) >>> hash(x) -9223372036852064692 >>> hash(y) -9223372036852064683 >>> id(x) 43377864 >>> x = (i for i in [0, 1, 2, 3, 4, 5, 6]) >>> id(x) 43378296 >>> hash(x) -9223372036852064665
As for why Python allows you to use them, it also allows you to hash all kinds of objects for the same reason: so you can separate different objects and use them as dictionary keys. This does not mean that you will talk about what the generator does, but which object. This is no different from this:
>>> hash(object()) 225805 >>> hash(object()) 225805 >>> x = object() >>> y = object() >>> hash(x) 225805 >>> hash(y) 225806
The idea that if an object is hashable, then it is immutable, is something of a misunderstanding. Objects can define any hash they want if it is compatible with their own definition of equality. For example, instances of custom classes are hashed in a manner similar to these generator functions (a hash based on an object identifier).
People sometimes seem to think that the rule "if an object is modified, it is not hashed," but this is not true. The actual rule is more like "if the object is not hashed, then it is modified." (More specifically, it defines the concept of equality, which depends on the state being changed, or it explicitly prohibits hashing for some perverse reason.) In other words, it usually doesn't make sense to ask why a particular hashed type is hashed; it makes sense to ask why the split type is unfastened. The built-in list of mutable types, dict and set have a specific reason for unlocking: they are intended for comparison based on their (mutable) values, and not on the identifier of the object. But just because some other type has some kind of internal state does not mean that it cannot be hashed. You can define objects that change and hashed throughout the day. They just have to define equality and hashability in compatible ways. Generators really cannot be compared for equality based on their contents:
>>> x = (i for i in [0, 1, 2, 3, 4, 5, 6]) >>> y = (i for i in [0, 1, 2, 3, 4, 5, 6]) >>> x == y False
For generators, value-based hashing would be unambiguously pointless because values ββdo not exist until they are actually obtained from the generator. If the hashing was based on values, there would be no way to hash a generator that, for example, would use random numbers to decide what comes next.