On 31/03/2021 11:31 pm, Brandt Bucher wrote:
Guido van Rossum wrote:
On Wed, Mar 31, 2021 at 2:14 PM Brandt Bucher brandtbuc...@gmail.com
wrote:
(One change from my last email: it doesn't allow `__match_map__` /
`__match_seq__` to be set to `False`... only `True`. This prevents some
otherwise tricky multiple-inheritance edge-cases present in both of our
flagging systems that I discovered during testing. I don't think there are
actual use-cases for unsetting the flags in subclasses, but we can revisit
that later if needed.)
That's surprising to me. Just like we can have a class that inherits from
int but isn't hashable, and make that explicit by setting `__hash__ =
None`, why couldn't I have a class that inherits from something else that
happens to inherit from Sequence, and say "but I don't want it to match
like a sequence" by adding `__match_sequence__ = False`? AFAIK all Mark's
versions would support this by setting `__match_kind__ = 0`.
The issue isn't when *I* set `__match_seq__ = False` or `__match_container__ =
0`. It's when *one of my parents* does it that things become difficult.
Maybe you can show an example edge case where this would be undesirable?
Good idea. I've probably been staring at this stuff for too long to figure it
out myself. :)
As far as I can tell, these surprising cases arise because a bit flag can only be either
0 or 1. For us, "not specified" is equivalent to 0, which can lead to ambiguity.
Consider this case:
```
class Seq:
__match_seq__ = True
# or __match_container__ = MATCH_SEQUENCE
class Parent:
pass
class Child(Parent, Seq):
pass
```
Okay, cool. `Child` will match as a sequence, which seems correct. But what
about this similar case?
```
class Seq:
__match_seq__ = True
# or __match_container__ = MATCH_SEQUENCE
class Parent:
__match_seq__ = False
# or __match_container__ = 0
class Child(Parent, Seq):
pass
```
Here, `Child` will *not* match as a sequence, even though it probably should. The only
workarounds I've found (like allowing `None` to mean "this is unset, don't inherit
me if another parent sets this flag", ditching tp_flags entirely, or not inheriting
these attributes) feel a bit extreme just to allow some users to do the moral equivalent
of un-subclassing `collections.abc.Sequence`.
This is just a weird case, so I don't think we should worry about it too
much.
So, my current solution (seen on the branch linked in my earlier email) is:
- Set the flag if the corresponding magic attribute is set to True in the class
definition
- Raise at class definition time if it's set to anything other than True
- Otherwise, set the flag if any of the parents set have the flag set
As far as I can tell, this leads to the expected (and current, as of 3.10.0a6)
behavior in all cases. Plus, it doesn't break my mental model of how
inheritance works.
Inheritance in Python is based on the MRO (using the C3 linearization
algorithm) so my mental model is that Child.__match_container__ == 0.
Welcome the wonderful world of multiple inheritance :)
If Parent.__match_container__ == 0 (rather than just inheriting it) then
it is explicitly stating that it is *not* a container.
Seq explicitly states that it *is* a sequence.
So Child is just broken. That it is broken for pattern matching is
consistent with it being broken in general.
Cheers,
Mark.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/python-dev@python.org/message/R3BGDN6NINJMLUWBVMVYIGORSLPJOMJP/
Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/python-dev@python.org/message/Z7TK37K25DOV6LSWZDXA7HDXOTKGZTUP/
Code of Conduct: http://python.org/psf/codeofconduct/