This should work:
from typing import *
T = TypeVar('T') # Any type.
ValueOrCallable = Union[T, Callable[..., T]]
class Foo(object):
state: ClassVar[ValueOrCallable]
Answer from Victor Ruiz on Stack OverflowThis should work:
from typing import *
T = TypeVar('T') # Any type.
ValueOrCallable = Union[T, Callable[..., T]]
class Foo(object):
state: ClassVar[ValueOrCallable]
Your attempts didn't work because of two reasons:
- The type qualifier
ClassVarcannot be used in type aliases; it must be used directly in the class body. - A call expression (e.g.
identifier()) is not a valid annotation expression. In other words, it won't be recognized as a valid type hint by spec-compliant type checkers.
Thus, the type alias should be specified as:
# 3.12+
type ValueOrCallable[T] = T | Callable[[SomeObject], T]
# 3.10, 3.11
from typing import TypeAlias, TypeVar
T = TypeVar('T')
ValueOrCallable: TypeAlias = T | Callable[[SomeObject], T]
...and used as:
(playgrounds: Mypy, Pyright)
class Foo:
state: ClassVar[ValueOrCallable[str]]
number: ClassVar[ValueOrCallable[int]]
foobar: ClassVar[ValueOrCallable[bool]]
Videos
I don't know of an easy way to make the type definition itself parameterisable without making it a class unto itself.
But perhaps this is close enough to what you want:
from typing import TypeVar
class MyClass:
pass
# instead of defining a parameterisable type, why not define the types you need?
MyType = TypeVar('MyType', MyClass, str, None)
def fun(x: MyType):
if isinstance(x, MyClass):
print('MyClass', x)
elif isinstance(x, str):
print('str', x)
elif x is None:
print('None')
else:
print('Something unexpected was passed')
fun(MyClass())
fun('test')
fun(None)
fun(1)
Output:
MyClass <__main__.MyClass object at 0x0000028D566CEA10>
str test
None
Something unexpected was passed
And in editors that check for it (for example in my case PyCharm), you get a warning like "Expected type 'MyType', got 'int' instead" on the last line fun(1), specifically on the 1.
Note: from the comments you've made it clear this is not ideal for you, but I'll leave the answer up for others looking and deciding it does work for them.
Define a TypeVar and a class that inherits from Union
In my example you see me inheriting from tuple actually,
but it is just to show that b really has inferred type str
from typing import *;
T = TypeVar("T");
class TupleAlias(tuple[T, str, None]): ...
def f(u: TupleAlias[int]):
a, b, c = u;
return b.capitalize();
pass
(in the picture, you should see completions for str type)
