Two more bits of bikeshedding…
On Sep 5, 2019, at 12:12, Andrew Barnert via Python-ideas
<[email protected]> wrote:
>
>> On Sep 5, 2019, at 04:24, Steven D'Aprano <[email protected]> wrote:
>>
>> If Union is a built-in, we could have something like this:
>>
>> def isinstance(obj, class_or_tuple):
>> if type(class_or_tuple) is Union:
>> class_or_tuple = class_or_tuple.__union_params__
>> # followed by the same code as above
>>
>> typing.Union already defines .__union_params__ which returns a tuple of
>> the classes used to construct the union, so in principle at least, there
>> need be no significant performance hit from supporting Unions.
>
> That’s a great point.
>
> And if type.__or__ is going to return a union type, we probably don’t want
> that to go lazily importing typing and pulling something out of it to call
> __getitem__ on, so we probably want that result to be builtin.
>
> I don’t think we need Union itself to be a builtin. But
> typing.Union.__getitem__ needs to return the same kind of builtin as
> type.__or__ (which is presumably exposed as something like types.UnionType,
> not only exposed in the typing module) instead of returning a
> typing._GenericAlias, or the whole point of this proposal (that `int|str ==
> Union[int, str]`) breaks.
>
> That does raise some more bikeshedding questions (what the constructor for
> types.union accepts, or whether it refuses to be constructed and forces you
> to use type.__or__ or Union.__getitem__; what its repr looks like; etc.).
Also:
Are runtime union types actually types, unlike the things in typing, or are
they still non-type values that just have special handling as the second
argument of isinstance and issubclass and maybe except statements?
I’d expect issubclass(int|str, int|str|bytes) to be true, and
issubclass(int|str, int) to be false, not for both of them to raise exceptions
about the first argument not being a type.
And I don’t see any reason that “things designed to be used as types for
runtime type checks” shouldn’t be types. And their type (types.UnionType or
whatever) a perfectly normal metaclass that inherits from type.
But, other than the issubclass question, I’m having a hard time imagining
anywhere that it would make a difference.
While we’re at it:
issubclass(int|str, types.UnionType)
I think this should be false because UnionType is not like typing.Union (which
is a typing.Generic, and therefore on its own it has to have the useless
meaning of “the type that includes all values of any unions of any 1 or more
types), it’s just a normal metaclass (with the normal meaning “the type of all
union types”).
Finally, do we still need the existing Generic, typing.Union, at all? If
types.UnionType defines a __getitem__, we could just do Union =
types.UnionType. Would this do the right thing in every case, or could it break
anything? I don’t know; I think it’s safer to leave typing.Union as-is (except
for defining its __getitem__ to return the | of all of its arguments, instead
of inheriting the _SpecialForm.__getitem__ behavior).
_______________________________________________
Python-ideas mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/PRKCGCX4X2GPP4JMZGWIKGG2ZF5IAURF/
Code of Conduct: http://python.org/psf/codeofconduct/