Curso
Uma necessidade comum em programas Python é verificar se pelo menos um elemento de uma estrutura de dados é True.
Embora seja possível escrever um loop para percorrer um iterável e checar se cada item avalia para True ou False, a função any() do Python é uma forma mais eficiente e "pythônica" de chegar a esse resultado.
Este tutorial explora a função embutida any() do Python e mostra vários exemplos e casos de uso.
Aprimoramento de IA para iniciantes
O que a função any() do Python faz?
A função any() é uma das funções embutidas do Python. Ela aceita um iterável como uma lista ou tupla, e retorna True se pelo menos um valor no iterável for truthy. Um valor truthy é avaliado como True quando convertido para Boolean com bool(). Se todos os valores do iterável forem falsy, any() retorna False:
print(any([True, False, False, True]))
print(any([False, False, False, False]))
print(any([0, 0, 5, 0]))
True
False
True
O iterável pode conter valores booleanos ou outros objetos, já que todos os objetos são avaliados como True ou False quando convertidos para Boolean. No terceiro exemplo, a lista inclui quatro inteiros. O inteiro 0 é falsy, mas todos os números diferentes de zero são truthy. Para entender melhor a diferença entre valores truthy e falsy, leia este artigo sobre operadores lógicos em Python.
Se o iterável estiver vazio, any() retorna False, já que não há valores truthy em um iterável vazio:
print(any([]))
False
A próxima seção aprofunda como any() funciona.
Como any() funciona?
A função embutida any() aceita qualquer iterável como argumento. Um iterável é qualquer estrutura de dados que o Python consegue percorrer em loop.
Considere a seguinte tupla:
an_iterable = ("", 0.0, "DataCamp", False, [])
A tupla inclui vários objetos de tipos diferentes. Alguns desses objetos são falsy:
- A string vazia
"" - O float
0.0 - O booleano
False - A lista vazia
[]
Esses objetos são falsy porque são avaliados como False quando passados para bool().
A string não vazia "DataCamp" é truthy.
Uma forma direta de verificar se pelo menos um elemento é truthy é usar um loop for:
def check_if_contains_truthy(data):
output = False
for item in data:
if item:
output = True
return output
print(check_if_contains_truthy(an_iterable))
True
No entanto, isso é ineficiente, já que a função só precisa checar se existe pelo menos um valor truthy. Assim que encontra um valor truthy, não é necessário continuar verificando o restante dos itens do iterável. A função pode ser modificada para retornar assim que encontrar o primeiro valor truthy:
def check_if_contains_truthy(data):
for item in data:
if item:
return True
return False
print(check_if_contains_truthy(an_iterable))
True
Uma instrução return interrompe a execução da função. Portanto, quando a função encontra o primeiro valor truthy, ela retorna True e não continua iterando sobre o iterável. A função retorna False apenas se o loop for percorrer todos os itens do iterável e nenhum deles for truthy.
A any() embutida segue um padrão semelhante e faz short-circuit assim que encontra o primeiro valor truthy. Essa avaliação preguiçosa evita operações desnecessárias e melhora a performance. A any() do Python é uma versão mais eficiente da função acima. Essa eficiência maior é confirmada usando a função timeit() do módulo timeit, que mede quanto tempo o Python leva para executar uma instrução:
from timeit import timeit
print("Execution time for 'check_if_contains_truthy()'")
print(
timeit(
"check_if_contains_truthy(an_iterable)",
number=10_000_000,
globals=globals(),
)
)
print("Execution time for 'any()'")
print(
timeit(
"any(an_iterable)",
number=10_000_000,
globals=globals(),
)
)
Execution time for 'check_if_contains_truthy()'
0.6335119580035098
Execution time for 'any()'
0.39488654200249584
O primeiro argumento de timeit() é uma string com a instrução a ser executada. O segundo argumento define quantas vezes executar a instrução. Neste exemplo, ambas as instruções são executadas 10.000.000 de vezes para obter tempos significativos. O último argumento repassa as variáveis globais para a função timeit().
A any() do Python é mais rápida que check_if_contains_truthy(). Usar any() para identificar se um iterável tem pelo menos um valor truthy é mais pythônico e eficiente do que usar um loop for.
Casos de uso de any()
Vamos ver alguns casos de uso da any() no Python.
Verificar se pelo menos uma entrada do usuário é válida
Considere uma série de entradas do usuário coletadas em uma lista ou tupla. Um programa pode precisar verificar se pelo menos uma das entradas é válida, por exemplo, se é uma string não vazia:
user_inputs = ["", "10.99", ""]
if any(user_inputs):
print("At least one valid input present")
# Rest of code...
else:
print("There are no valid inputs")
At least one valid input present
Como uma das strings não está vazia, any() retorna True, e o código dentro do bloco if é executado.
Verificar se pelo menos um arquivo existe
A any() embutida pode ser usada para verificar se pelo menos um arquivo em uma lista de nomes existe em um diretório:
from pathlib import Path
files = ["article.md", "use_any.py", "scratch.py", "test_file.txt"]
cwd = Path.cwd()
# Create a test file to test code
Path("test_file.txt").write_text("This is a test file")
if any(Path(file).exists() for file in files):
print("At least one of the files exists")
# Rest of code…
else:
print("None of the files exist")
At least one of the files exists
O código obtém o diretório de trabalho atual usando o módulo pathlib e Path.cwd(). Ele cria um arquivo chamado test_file.txt no diretório de trabalho para facilitar o teste do código. A função any() é usada para verificar se pelo menos um dos nomes de arquivo existe no diretório de trabalho atual.
Filtrar itens de um iterável
A função embutida any() também pode ser usada com uma expressão geradora como argumento para filtrar itens de um iterável. Neste exemplo, any() procura por pelo menos um registro em uma lista de dicionários que representa uma pessoa cuja idade é menor que 18:
records = [
{"name": "Sarah", "age": 23},
{"name": "Jake", "age": 30},
{"name": "Paul", "age": 17},
]
if any(record["age"] < 18 for record in records):
print("There's at least one minor.")
else:
print("All records are adults.")
There's at least one minor.
A expressão geradora produz True ou False conforme o valor correspondente à chave "age" de cada dicionário. Uma expressão geradora pode ser usada em any() por ser iterável.
Revisitando a avaliação preguiçosa na any() do Python
O exemplo anterior também pode demonstrar que any() é avaliada de forma preguiçosa. Considere a seguinte modificação na lista de dicionários:
records = [
{"name": "Sarah", "age": 23},
{"name": "Jake", "age": 30},
{"name": "Paul", "age": 17},
{"name": "Jill"},
]
if any(record["age"] < 18 for record in records):
print("There's at least one minor.")
else:
print("All records are adults.")
There's at least one minor.
O quarto dicionário em records não contém um item com a chave "age". No entanto, o código não gera erro ao tentar buscar o valor correspondente a "age" para esse item porque any() encontrou um valor truthy antes. A função faz short-circuit quando encontra o primeiro valor truthy.
O código gera um KeyError se o dicionário sem a chave "age" vier antes de qualquer item com idade abaixo de 18:
records = [
{"name": "Jill"},
{"name": "Sarah", "age": 23},
{"name": "Jake", "age": 30},
{"name": "Paul", "age": 17},
]
if any(record["age"] < 18 for record in records):
print("There's at least one minor.")
else:
print("All records are adults.")
Traceback (most recent call last):
...
if any(record["age"] < 18 for record in records):
~~~~~^^^^^^
KeyError: 'age'
Este exemplo foi projetado para demonstrar o comportamento de short-circuit ao usar a any() do Python. Há uma alternativa caso o código não deva lançar exceções para itens sem a chave "age". Pode-se usar o método .get() do dicionário com um valor padrão, em vez de acessar um valor usando a notação de colchetes. A instrução if pode ser substituída pela versão abaixo se o comportamento padrão for assumir que entradas sem idade não são menores:
if any(record.get("age", 18) < 18 for record in records):
# ...
Se o código deve assumir que qualquer entrada sem idade é menor de idade, o valor padrão precisa ser menor que 18.
Python: any() vs. all()
A any() do Python tem uma função complementar, all(). Essa função embutida também aceita um iterável e retorna True se todos os itens do iterável forem truthy.
Considere um exemplo anterior deste tutorial para validar entradas de usuário. A any() é útil se o aplicativo exigir pelo menos uma entrada válida. Já a all() pode ser usada se todas as entradas do usuário precisarem ser válidas:
user_inputs = ["", "10.99", ""]
if any(user_inputs):
print("At least one valid input present")
# Rest of code...
else:
print("There are no valid inputs")
if all(user_inputs):
print("All inputs are valid")
# Rest of code...
else:
print("Not all inputs are valid")
At least one valid input present
Not all inputs are valid
Porém, se todas as strings nas entradas do usuário forem não vazias, all() retorna True:
user_inputs = ["5.99", "10.99", "19.99"]
# …
At least one valid input present
All inputs are valid
Assim como any(), a função embutida all() também é avaliada de forma preguiçosa. A função faz short-circuit quando encontra o primeiro valor falsy.
Conclusão
A any() do Python verifica se algum dos itens em um iterável é truthy. A função retorna True se pelo menos um item no iterável for True ou avaliar para True quando convertido para Boolean. Embora seja possível obter o mesmo resultado usando um loop, essa função embutida oferece uma solução mais legível e eficiente.
Obtenha uma das melhores certificações de IA
Estudei Física e Matemática em nível superior na Universidade de Malta. Depois, mudei-me para Londres e fiz meu doutorado em Física no Imperial College. Trabalhei em novas técnicas ópticas para obter imagens da retina humana. Agora, meu foco é escrever sobre Python, comunicar sobre Python e ensinar Python.
