On 2/2/2018 10:38 AM, Elvis Pranskevichus wrote:
On Friday, February 2, 2018 10:08:43 AM EST Eric V. Smith wrote:
However, I don't feel very strongly about this. As I've said, I expect
the use cases for hash=True to be very, very rare.

Why do you think that the requirement to make a dataclass hashable is a
"very, very rare" requirement?  The moment you want to use a dataclass a
a dict key, or put it in a set, you need it to be hashable.

I was specifically talking about the case of a non-frozen, hashable class. If you want to make a class frozen and hashable, then:

@dataclass(frozen=True)

will do just that.

The case you brought up initially is the non-frozen, hashable class. It's that case that I think is very rare. I'll ask again: what's your use case for wanting a non-frozen, hashable class? I'm genuinely interested.

You seem to think that hash=True means "make the class hashable". That's not true. It means "add a __hash__" to this class". There are other, better ways to make the class hashable, specifically frozen=True. You might want to read all of https://bugs.python.org/issue32513 for the background on the current behavior.

Just put yourself in the shoes of an average Python developer.  You try
to put a dataclass in a set, you get a TypeError.  Your immediate
reaction is to add "hash=True".  Things appear to work.  Then, you, or
someone else, decides to mutate the dataclass object and then you are
looking at a very frustrating debug session.

I will be documented that the correct way to do this is frozen=True.

In all, I think we're better off documenting best practices and making
them the default, like attrs does, and leave it to the programmer to
follow them. I realize we're handing out footguns

I don't think attrs doing the same thing is a valid justification.  This
is a major footgun that is very easy to trigger, and there's really no
precedent in standard data types.

the alternatives seem even more complex and are limiting.

The alternative is simple and follows the design of other standard
containers: immutable containers are hashable, mutable containers are
not.  @dataclass(frozen=False) gives you a SimpleNamespace-like and
@dataclass(frozen=True) gives you a namedtuple-like.  If you _really_
know what you are doing, then you can always declare an explicit
__hash__.

I'm not sure what you're arguing for here. This is how dataclasses work.

The problem with dropping hash=True is: how would you write __hash__
yourself?

Is "def __hash__(self): return hash((self.field1, self.field2))" that
hard?  It is explicit, and you made a concious choice, i.e you
understand how __hash__ works.

I didn't say it was hard, I said it needed to be kept up to date as you add fields. That is, you'd have to duplicate the field list. dataclasses is trying to prevent you from repeating the field list anywhere.

IMO, the danger of
"@dataclass(hash=True)" far overweighs whatever convenience it might
provide.

We'll just have to disagree about this. As I said, I don't feel very strongly about it, but I lean toward leaving it in and documenting it for what it is and does.

Eric
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to