Python method return type

How to specify multiple return types using type-hints

I have a function in python that can either return a bool or a list . Is there a way to specify the return types using type hints? For example, is this the correct way to do it?

@PadraicCunningham Perhaps the implementation is I’ll send you my Id, you send me either a list or a boolean 😀

@PadraicCunningham Polymorphism. If your function performs a check on the input, whatever it is, you want to get a boolean when you feed one variable or get a list of booleans when you feed a list of variables.

4 Answers 4

A union object holds the value of the | (bitwise or) operation on multiple type objects. These types are intended primarily for type annotations. The union type expression enables cleaner type hinting syntax compared to typing.Union .

This use of | was added in Python 3.10. Hence the proper way to represent more than one return data type is:

def foo(client_id: str) -> list | bool: 
from typing import Union def foo(client_id: str) -> Union[list, bool]: 

But do note that typing is not enforced. Python continues to remain a dynamically-typed language. The annotation syntax has been developed to help during the development of the code prior to being released into production. As PEP 484 states, «no type checking happens at runtime.»

>>> def foo(a: str) -> list: . return "Works" . >>> foo(1) 'Works' 

As you can see I am passing an int value and returning a str. However the __annotations__ will be set to the respective values.

Читайте также:  Путь до файла python linux

Please go through PEP 483 for more about Type hints. Also see What are type hints in Python 3.5??

Kindly note that this is available only for Python 3.5 and upwards. This is mentioned clearly in PEP 484.

Источник

Python Typing: declare return value type based on function argument

That list is not exhaustive, I’d like to be able to use any type with appropriate constructor. Then, I’d like to add type hints for that function. What should be the type hint for return value of that function? I’ve tried using simply t , as t is a type:

def fun(t: type) -> t: return t(42) 
from typing import TypeVar T = TypeVar("T") def fun(t: T) -> T: return t(42) 

But that doesn’t seem to be right, as T denotes a type, so it suggests that type itself is returned, not its instance. Mypy rejects it:

from typing import Any def fun(t: type) -> Any: return t(42) 

Related question: Python type hint for (any) class — Stack Overflow ■ Side note, if you don’t require fun to be a function and the return value is’ custom class you may want to make that class generic and call it like Fun[Union[int, float]]() .

2 Answers 2

TLDR: You need a TypeVar for the return type of calling t :

def fun(t: Callable[[int], R]) -> R: . 

Constraining on a type is too restrictive here. The function accepts any Callable that takes an integer, and the return type of the function is that of the Callable . This can be specified using a TypeVar for the return type:

from typing import Callable, TypeVar R = TypeVar('R') # the variable return type def fun(t: Callable[[int], R]) -> R: return t(42) fun(int) # Revealed type is 'builtins.int*' fun(float) # Revealed type is 'builtins.float*' reveal_type(fun(lambda x: str(x))) # Revealed type is 'builtins.str*' 

This works for types as well, because type instantiation is a call.

If a more complex signature, e.g. with keyword arguments, is needed, use Protocol (from typing or typing_extensions ).

Note that if one explicitly wants to pass only 42 to the Callable , Literal (from typing or typing_extensions ) can be used to specify that.

R = TypeVar('R') def fun(t: Callable[[Literal[42]], R]) -> R: return t(42) 

Note that any function of the type Callable[[int], R] also satisfies Callable[[Literal[42]], R] .

Источник

Type hinting the return value of a class method that returns self?

Things that might be of help: hovering over the method foo with no annotations of a return value, VScode hints shows — Self@A , i dont understand it but, this definitely differentiates between returning another instantiated class A() and returning self . Thanks

My best guess is you can’t really do this in python — you would require a value-dependent type that allows you to distinguish between different instances of a single simply typed object A, something that python’s typing ecosystem does not support.

To add to that. The purpose of type hinting is to specify type, not instance. So what you want is probably not possible. Python 3.11 will have a Self type but in this particular example (without inheritance) it does the same as just specifying A , i.e. allowing all instances of that type. peps.python.org/pep-0673

2 Answers 2

I can’t find any question that covers this closely, so will try to explain.

What does «same type» mean for type checking

Well, probably this is the long form of «you can’t, and you shouldn’t».

Type checking aims to confirm that all functions are called with proper argument types and return expected types. I suggest to read PEP483 first to understand concept of type better. Suppose you have the following:

s1 = ''.join(['a', 'b', 'c']) s2 = ''.join(['a', 'b', 'c']) assert s1 is not s2 assert s1 == s2 

( join to avoid optimization, but it’s another story). Are they the same object? No, is not clearly states this (they have different memory addresses). But will s2 be acceptable whenever you want s1 ? Definitely yes. You will not create a function that operates only on s1 and checks this fact with is , right?

Now what is the difference between self as reference to exact object and self as any A instance? When we talk about type checking, all A instances are completely equivalent and indistinguishable. They have the same set of methods and attributes (including types). We can ask: «which type errors can be introduced or removed, if we explicitly declare object to be self instance and not just self type?» I really cannot think of any. If you want this for semantics, use docstring — types should not be abused for everything. self object is absolutely the same as any other A() instance for type checker.

Simple solution: return class instance

Your first code sample is almost fine. Annotate return as A to tell that it returns instance of class A , it will work for final class:

class A: def foo(self) -> A: return self 

However, this approach has a drawback (it is good explained in PEP673 about Self type):

class AChild(A): pass # mypy reveal_type(AChild().foo()) # N: revealed type is "__main__.A" 

If you create new A in foo and return it, then this approach is perfect. If you return self — it is valid, but not precise. That’s why we need Self type.

Self type

Self type was introduced in PEP673, and was not supported by mypy at the time of writing this. Your usage in 3rd example was perfectly valid and will work after implementation in type checkers (see 5-th code block in «Motivation» section of PEP). The support was added to mypy in version 1.0 , so if you’re using this version or later — this section is the proper answer.

Here’s how you can use Self (assuming python=3.11 not to bother with typing_extensions ):

from typing import Self class A: def foo(self) -> Self: return self class AChild(A): pass # mypy reveal_type(AChild().foo()) # N: revealed type is "__main__.AChild" reveal_type(A().foo()) # N: revealed type is "__main__.A" 

Implementing Self type without using it

However, you can mimic Self accurately with a few lines of code (and python >= 3.7 , AFAIR).

from typing import TypeVar _Self = TypeVar('_Self', bound='A') class A: def foo(self: _Self) -> _Self: return self class AChild(A): pass # mypy reveal_type(AChild().foo()) # N: revealed type is "__main__.AChild" reveal_type(A().foo()) # N: revealed type is "__main__.A" 

Now this works. All subclasses will return their class instance.

Источник

Оцените статью