Como especificar vários tipos de retorno usando dicas de tipo


205

Eu tenho uma função em python que pode retornar um boolou um list. Existe uma maneira de especificar os tipos de retorno usando dicas de tipo.

Por exemplo, esta é a maneira correta de fazer isso?

def foo(id) -> list or bool:
      ...

5
como você acaba com uma lista ou um booleano?
Padraic Cunningham

11
@PadraicCunningham Talvez a implementação é que eu vou lhe enviar minha Id, você me enviar uma lista ou um booleano : D
Bhargav Rao

provavelmente, que é fraca implementação
Sławomir Lenart

@PadraicCunningham Polymorphism. Se sua função executa uma verificação na entrada, seja ela qual for, você deseja obter um booleano ao alimentar uma variável ou obter uma lista de booleanos ao alimentar uma lista de variáveis.
Guimoute 20/02

Respostas:


282

A partir da documentação

classe typing.Union

Tipo de união; União [X, Y] significa X ou Y.

Portanto, a maneira correta de representar mais de um tipo de dados de retorno é

from typing import Union


def foo(client_id: str) -> Union[list,bool]

Mas observe que a digitação não é imposta. O Python continua sendo uma linguagem de tipo dinâmico. A sintaxe da anotação foi desenvolvida para ajudar durante o desenvolvimento do código antes de ser liberado na produção. Como afirma o PEP 484, "nenhuma verificação de tipo acontece em tempo de execução".

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

Como você pode ver, estou passando um valor int e retornando um str. No entanto, o valor __annotations__será definido para os respectivos valores.

>>> foo.__annotations__ 
{'return': <class 'list'>, 'a': <class 'str'>}

Consulte o PEP 483 para obter mais informações sobre dicas de tipo. Consulte também O que são dicas de tipo no Python 3.5 ?

Observe que isso está disponível apenas para Python 3.5 e superior. Isso é mencionado claramente no PEP 484 .


Existe um equivalente no Python 3.4
Yahya Uddin

1
@YahyaUddin Nope - PEP 484 : '(.... É apenas para Python3.5 em diante.
Bhargav Rao

1
@YahyaUddin Bastante surpreendente. Você quis dizer Anotações de Função por acaso?
Bhargav Rao

2
Então deixe-me ver se entendi. O Python 3.4 possui anotações de funções que não fazem nada além de anotações que NÃO são impostas. Mas no Python 3.5, essa é uma verificação de tipo real.
Yahya Uddin

1
@BhargavRao, desculpe por isso! Eu apenas senti que era muito importante deixar na seção de comentários.
Bobort

26

A declaração, def foo(client_id: str) -> list or bool:quando avaliada, é equivalente def foo(client_id: str) -> list:e, portanto, não fará o que você deseja.

A maneira nativa de descrever uma dica do tipo "A ou B" é Union (graças a Bhargav Rao):

def foo(client_id: str) -> Union[list, bool]:

Eu não quero ser o cara "Por que você quer fazer isso de qualquer maneira", mas talvez ter dois tipos de retorno não seja o que você deseja:

Se você deseja retornar um bool para indicar algum tipo de caso de erro especial, considere usar exceções. Se você deseja retornar um bool como algum valor especial, talvez uma lista vazia seja uma boa representação. Você também pode indicar que Nonepode ser retornado comOptional[list]


6
Existem usos em que o retorno de vários tipos pode ser o que você deseja: por exemplo, se você precisar retornar um de algum conjunto de subtipos, mas não outros, ou se estiver tentando processar dados e quiser retornar o formulário bruto, se o processamento não for possível. não está disponível. Além disso, se você estiver agrupando o código legado, ele poderá ser bastante útil, pois ajuda no processo de atualização e / ou em lugares estranhos.
Nathaniel Ford

As exceções e a ideia de lista vazia também foram úteis. Obrigado
Yahya Uddin

20

Caso alguém tenha chegado aqui em busca de "como especificar tipos de vários valores de retorno?", Use Tuple[type_value1, ..., type_valueN]

from typing import Tuple

def f() -> Tuple[dict, str]:
    a = {1: 2}
    b = "hello"
    return a, b

Mais informações: https://code-examples.net/en/q/2651e60

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.