Before 3.10, I was using Union
to create union parameter annotations:
from typing import Union
class Vector:
def __mul__(self, other: Union["Vector", float]):
pass
Now, when I use the new union shorthand syntax:
class Vector:
def __mul__(self, other: "Vector" | float):
pass
I get the error:
TypeError: unsupported operand type(s) for |: 'str' and 'type'
Is this not supported?
The fact that it's being used as a type hint doesn't really matter; fundamentally the expression "Vector" | float
is a type error because strings don't support the |
operator, they don't implement __or__
. To get this passing, you have three options:
Defer evaluation (see PEP 563):
from __future__ import annotations
class Vector:
def __mul__(self, other: Vector | float): ...
Make the whole type a string (effectively the same as deferring evaluation):
class Vector:
def __mul__(self, other: "Vector | float"): ...
Keep using the Union
:
from typing import Union
class Vector:
def __mul__(self, other: Union["Vector", float]): ...
You can see further discussion on this bug, resolved by documenting the behaviour explicitly:
Note: The
|
operand cannot be used at runtime to define unions where one or more members is a forward reference. For example,int | "Foo"
, where"Foo"
is a reference to a class not yet defined, will fail at runtime. For unions which include forward references, present the whole expression as a string, e.g."int | Foo"
.