Pergunta

Não me lembro se estava sonhando ou não, mas parece que me lembro de haver uma função que permitia algo como,

foo in iter_attr(array of python objects, attribute name)

Examinei os documentos, mas esse tipo de coisa não se enquadra em nenhum cabeçalho listado óbvio

Foi útil?

Solução

Usar uma compreensão de lista criaria uma lista temporária, que poderia consumir toda a sua memória se a sequência pesquisada fosse grande.Mesmo que a sequência não seja grande, construir a lista significa iterar toda a sequência antes in poderia iniciar sua busca.

A lista temporária pode ser evitada usando uma expressão geradora:

foo = 12
foo in (obj.id for obj in bar)

Agora, enquanto obj.id == 12 perto do início de bar, a busca será rápida, mesmo que bar é infinitamente longo.

Como sugeriu @Matt, é uma boa ideia usar hasattr se algum dos objetos em bar pode estar faltando um id atributo:

foo = 12
foo in (obj.id for obj in bar if hasattr(obj, 'id'))

Outras dicas

Você está procurando uma lista de objetos que possuem um determinado atributo?Se assim for, um compreensão da lista é a maneira certa de fazer isso.

result = [obj for obj in listOfObjs if hasattr(obj, 'attributeName')]

você sempre pode escrever um:

def iterattr(iterator, attributename):
    for obj in iterator:
        yield getattr(obj, attributename)

funcionará com qualquer coisa que itere, seja uma tupla, lista ou qualquer outra coisa.

Eu adoro python, ele torna coisas assim muito simples e não mais complicadas do que o necessário, e em uso coisas como essa são extremamente elegantes.

Não, você não estava sonhando.Python tem um excelente sistema de compreensão de listas que permite manipular listas com bastante elegância e, dependendo exatamente do que você deseja realizar, isso pode ser feito de duas maneiras.Em essência, o que você está fazendo é dizer "Para item na lista se critérios.matches" e, a partir disso, você pode simplesmente iterar pelos resultados ou despejá-los em uma nova lista.

Vou citar um exemplo de Mergulhe no Python aqui, porque é muito elegante e eles são mais espertos do que eu.Aqui eles estão obtendo uma lista de arquivos em um diretório e, em seguida, filtrando a lista para todos os arquivos que correspondem a um critério de expressão regular.

    files = os.listdir(path)                               
    test = re.compile("test\.py$", re.IGNORECASE)          
    files = [f for f in files if test.search(f)]

Você poderia fazer isso sem expressões regulares, por exemplo, para qualquer coisa em que sua expressão no final retorne verdadeira para uma correspondência.Existem outras opções, como usar a função filter(), mas se eu fosse escolher, escolheria esta.

Eric Sipple

A função que você está pensando é provavelmente operator.attrgettter.Por exemplo, para obter uma lista que contém o valor do atributo "id" de cada objeto:

import operator
ids = map(operator.attrgetter("id"), bar)

Se você quiser verificar se a lista contém um objeto com um id == 12, então um método limpo e eficiente (ou seja,não itera a lista inteira desnecessariamente) a maneira de fazer isso é:

any(obj.id == 12 for obj in bar)

Se você quiser usar 'in' com attrgetter, mantendo a iteração lenta da lista:

import operator,itertools
foo = 12
foo in itertools.imap(operator.attrgetter("id"), bar)

O que eu estava pensando pode ser alcançado usando compreensões de lista, mas pensei que havia uma função que fazia isso de uma forma um pouco mais organizada.

ou seja'bar' é uma lista de objetos, todos com o atributo 'id'

A maneira funcional mítica:

foo = 12
foo in iter_attr(bar, 'id')

A forma de compreensão da lista:

foo = 12
foo in [obj.id for obj in bar]

Em retrospecto, a forma de compreensão da lista é bem legal de qualquer maneira.

Se você planeja pesquisar qualquer coisa de tamanho remotamente decente, sua melhor aposta será usar um dicionário ou conjunto.Caso contrário, você basicamente terá que percorrer cada elemento do iterador até chegar ao que deseja.

Se este não for necessariamente um código sensível ao desempenho, o modo de compreensão da lista deverá funcionar.Mas observe que é bastante ineficiente porque repassa cada elemento do iterador e depois volta novamente até encontrar o que deseja.

Lembre-se, python tem um dos algoritmos de hash mais eficientes que existe.Use isso a seu favor.

Eu penso:

#!/bin/python
bar in dict(Foo)

É nisso que você está pensando.Ao tentar ver se uma determinada chave existe em um dicionário em python (versão python de uma tabela hash), há duas maneiras de verificar.Primeiro é o has_key() método anexado ao dicionário e o segundo é o exemplo dado acima.Ele retornará um valor booleano.

Isso deve responder a sua pergunta.

E agora um pouco fora do assunto para vincular isso ao compreensão da lista resposta dada anteriormente (para um pouco mais de clareza). Compreensões de lista construir uma lista a partir de um básico para loop com modificadores.Como exemplo (para esclarecer um pouco), uma forma de usar o in dict construção de linguagem em um compreensão da lista:

Digamos que você tenha um dicionário bidimensional foo e você deseja apenas os dicionários de segunda dimensão que contêm a chave bar.Uma maneira relativamente simples de fazer isso seria usar um compreensão da lista com uma condicional da seguinte forma:

#!/bin/python
baz = dict([(key, value) for key, value in foo if bar in value])

Note o if bar in value no final da instrução **, esta é uma cláusula modificadora que informa ao compreensão da lista para manter apenas os pares de valores-chave que atendem à condicional.** Neste caso baz é um novo dicionário que contém apenas os dicionários de foo que contêm bar (espero não ter perdido nada naquele exemplo de código...você pode ter que dar uma olhada na documentação de compreensão da lista encontrada em Tutoriais docs.python.org e em secnetix.de, ambos os sites são boas referências caso você tenha dúvidas no futuro.).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top