Usando 'em' para coincidir com um atributo de objetos Python em uma matriz

votos
39

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

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

Eu olhei nos docs, mas esse tipo de coisa não se enquadra em nenhuma cabeçalhos listados óbvias

Publicado 03/08/2008 em 14:19
fonte usuário
Em outras línguas...                            


8 respostas

votos
38

Usando uma lista compreensão iria construir uma lista temporária, o que poderia comer toda a sua memória se a seqüência que está sendo procurado é grande. Mesmo se a sequência não é grande, construindo a lista significa iteração sobre o conjunto da seqüência antes inpoderia começar sua pesquisa.

A lista temporária pode ser evitando usando um gerador de expressão:

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

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

Como @ Matt sugeriu, é uma boa idéia usar hasattrse algum dos objetos no barpode estar faltando um idatributo:

foo = 12
foo in (obj.id for obj in bar if hasattr(obj, 'id'))
Respondeu 11/09/2008 em 23:42
fonte usuário

votos
10

Você está olhando para obter uma lista de objetos que possuem um determinado atributo? Se assim for, uma compreensão da lista é o caminho certo para fazer isso.

result = [obj for obj in listOfObjs if hasattr(obj, 'attributeName')]
Respondeu 03/08/2008 em 16:59
fonte usuário

votos
8

você sempre pode escrever um você mesmo:

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

irá trabalhar com qualquer coisa que interage, seja ele uma tupla, lista, ou o que quer.

Eu amo python, faz coisas como esta muito simples e não mais de um aborrecimento que o necessário, e em uso coisas como esta é extremamente elegante.

Respondeu 27/08/2008 em 21:13
fonte usuário

votos
4

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 de 12, em seguida, uma forma elegante e eficiente (ou seja, não iterar toda a lista desnecessariamente) para fazê-lo é:

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

Se você quiser usar 'em' com attrgetter, mantendo iteração preguiçoso da lista:

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

Respondeu 05/02/2011 em 09:10
fonte usuário

votos
4

Não, você não estava sonhando. Python tem uma muito excelente sistema de compreensão da lista que permite manipular listas muito elegantemente e, dependendo exatamente o que você quer realizar, isso pode ser feito de duas maneiras. Em essência, o que você está fazendo está dizendo "Para o item na lista se criteria.matches", e de que você pode apenas percorrer os resultados ou despejar os resultados em uma nova lista.

Vou berço um exemplo do Dive Into Python aqui, porque é muito elegante e são mais espertos do que eu. Aqui eles estão recebendo uma lista de arquivos em um diretório, em seguida, filtrar 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 seu exemplo, para qualquer coisa onde sua expressão no final retorna true para uma partida. Existem outras opções como usar a função de filtro (), mas se eu fosse para escolher, eu iria com isso.

Eric Sipple

Respondeu 03/08/2008 em 15:30
fonte usuário

votos
3

Se você está pensando em pesquisar qualquer coisa de tamanho remotamente decente, sua melhor aposta vai ser usar um dicionário ou um conjunto. Caso contrário, você tem basicamente para percorrer cada elemento do iterador até chegar ao que você quer.

Se isso não é necessariamente código sensível performance, então a compreensão da lista forma deve funcionar. Mas note que é bastante ineficiente, pois passa por cada elemento do iterador e depois volta por isso novamente até encontrar o que quer.

Lembre-se, python tem um dos algoritmos de hash mais eficientes ao redor. Usá-lo para sua vantagem.

Respondeu 27/08/2008 em 21:30
fonte usuário

votos
3

O que eu estava pensando pode ser conseguido usando compreensões lista, mas eu pensei que havia uma função que fez isso de uma maneira um pouco mais limpa.

ou seja, 'bar' é uma lista de objetos, todos os que têm o atributo 'id'

A forma funcional mítica:

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

A maneira compreensão da lista:

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

Em retrospectiva do caminho compreensão da lista é bastante puro de qualquer maneira.

Respondeu 03/08/2008 em 17:13
fonte usuário

votos
-1

Eu acho que:

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

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

Isso deve responder a sua pergunta.

E agora um pouco fora de tópico para amarrar isso em à compreensão da lista resposta dada anteriormente (para um pouco mais de clareza). Compreensões lista construir uma lista de um básico para o laço com modificadores. Como exemplo (para esclarecer um pouco), uma maneira de usar o in dictconstrutor de linguagem em uma compreensão da lista :

Digamos que você tenha um dicionário bidimensional fooe você só quer o segundo dicionários dimensão que contêm a chave bar. Uma forma relativamente simples de fazer isso seria usar uma 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-se a if bar in value, no final da declaração **, esta é uma cláusula de modificar que conta a compreensão de lista para manter apenas os pares chave-valor que satisfaçam a condicional. ** Neste caso bazé um novo dicionário que contém apenas os dicionários de foo que contêm bar (Espero que eu não perca nada nesse exemplo de código ... você pode ter que dar uma olhada na documentação compreensão da lista encontrada em docs.python.org tutoriais e na secnetix.de , ambos os sites são boas referências, se você tiver dúvidas no futuro.).

Respondeu 03/08/2008 em 16:47
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more