[Python-ideas] several different needs [Explicit variable capture list]

Random832 random832 at fastmail.com
Wed Jan 27 17:42:15 EST 2016


On Wed, Jan 27, 2016, at 17:15, Chris Angelico wrote:
> The nature of hash tables and equality is such that if an object's
> value (defined by __eq__) changes between when it's used as a key and
> when it's looked up, bad stuff happens. It's not just an optimization
> - it's a way for the dict subsystem to protect us against craziness.

This stands alone against all the things that it *could* protect users
against but doesn't due to the "consenting adults" principle.

Java allows ArrayLists to be HashMap keys and the sky hasn't fallen,
despite that language otherwise having far more of a culture of
protecting users from themselves and each other (i.e. it has stuff like
private, final, etc) than Python does.

We won't even protect from redefining math.pi, yet you want to prevent a
user from using as a key in a dictionary a value which _might_ be
altered while the dictionary is in use? This prevents all kinds of
algorithms from being used which would benefit from using a short-lived
dict/set to keep track of things. I think this came up a month or so ago
when we were talking about comparison of dict values views (which could
benefit from being able to use all the values in the dict as keys in a
Counter). They're not going to change while the algorithm is executing
unless the user does some weird multithreaded stuff or something truly
bizarre in a callback (and if they do? consenting adults.), and the dict
is thrown away at the end.

> Yes, you can bypass that protection:
> 
> class HashableList(list):
>     def __hash__(self): return hash(tuple(self))

That doesn't really work for my scenario described above, which requires
an alternate universe in which Python (like Java) requires *all*
objects, mutable or otherwise, to define __hash__ in a way consistent
with __eq__.

> but it's a great safety net. You won't unexpectedly get KeyError when
> you iterate over a dictionary - you'll instead get TypeError when you
> try to assign. Is that a semantic question or a performance one?

But I won't get either error if I don't mutate the list, or I only do it
in equality-conserving ways (e.g. converting between numeric types).


More information about the Python-ideas mailing list