Eu tenho uma lista de objetos Python que gostaria de classificar por um atributo dos próprios objetos. A lista se parece com:
>>> ut
[<Tag: 128>, <Tag: 2008>, <Tag: <>, <Tag: actionscript>, <Tag: addresses>,
<Tag: aes>, <Tag: ajax> ...]
Cada objeto tem uma contagem:
>>> ut[1].count
1L
Preciso classificar a lista pelo número de contagens decrescente.
Eu já vi vários métodos para isso, mas estou procurando as melhores práticas em Python.
Respostas:
Mais sobre a classificação por chaves .
fonte
Uma maneira que pode ser mais rápida, principalmente se a sua lista tiver muitos registros, é usar
operator.attrgetter("count")
. No entanto, isso pode ser executado em uma versão pré-operador do Python, portanto, seria bom ter um mecanismo de fallback. Você pode fazer o seguinte, então:fonte
self.__dict__ = {'some':'dict'}
após o__init__
método). Eu não sei por que deveria ser diferente, no entanto.__dict__
. Observe que "um objeto com atributos adicionados dinamicamente" e "definir o__dict__
atributo de um objeto " são conceitos quase ortogonais. Estou dizendo isso porque seu comentário parece sugerir que definir o__dict__
atributo é um requisito para adicionar atributos dinamicamente.operator.attrgetter
, eu poderia fornecer uma função com qualquer nome de propriedade e retornar uma coleção classificada.Os leitores devem observar que o método key =:
é muitas vezes mais rápido do que adicionar operadores de comparação avançados aos objetos. Fiquei surpreso ao ler isso (página 485 de "Python em poucas palavras"). Você pode confirmar isso executando testes neste pequeno programa:
Meus testes muito mínimos mostram que o primeiro tipo é 10 vezes mais lento, mas o livro diz que é apenas 5 vezes mais lento em geral. O motivo é que eles dizem que se deve ao algoritmo de classificação altamente otimizado usado em python ( timsort ).
Ainda assim, é muito estranho que .sort (lambda) seja mais rápido que o antigo .sort (). Espero que eles consertem isso.
fonte
__cmp__
é equivalente a chamar.sort(cmp=lambda)
, não.sort(key=lambda)
, por isso não é nada estranho.longList2.sort(cmp = cmp)
. Eu tentei isso e ele executou quase o mesmo que.sort()
. (Além disso: observe que o parâmetro de classificação "cmp" foi removido no Python 3.)Abordagem orientada a objetos
É uma boa prática criar lógica de classificação de objetos, se aplicável, uma propriedade da classe em vez de incorporar em cada instância em que a ordem é necessária.
Isso garante consistência e elimina a necessidade de código padrão.
No mínimo, você deve especificar
__eq__
e__lt__
operações para que isso funcione. Então é só usarsorted(list_of_objects)
.fonte
__eq__
e quais__lt__
são os requisitos mínimos de implementação?•The sort routines are guaranteed to use __lt__() when making comparisons between two objects...
fonte
Parece muito com uma lista de instâncias do modelo Django ORM.
Por que não classificá-los em consultas como esta:
fonte
Adicione operadores de comparação avançados à classe de objeto e use o método sort () da lista.
Veja uma comparação rica em python .
Atualização : Embora esse método funcione, acho que a solução da Triptych é mais adequada ao seu caso, porque é muito mais simples.
fonte
Se o atributo que você deseja classificar for uma propriedade , evite importar
operator.attrgetter
e usar os atributos da propriedade.fget
método .Por exemplo, para uma classe
Circle
com uma propriedade,radius
podemos classificar uma listacircles
por raio da seguinte maneira:Esse não é o recurso mais conhecido, mas geralmente me poupa uma linha com a importação.
fonte