Two more bits of bikeshedding…

On Sep 5, 2019, at 12:12, Andrew Barnert via Python-ideas 
<python-ideas@python.org> wrote:
> 
>> On Sep 5, 2019, at 04:24, Steven D'Aprano <st...@pearwood.info> 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 -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/PRKCGCX4X2GPP4JMZGWIKGG2ZF5IAURF/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to