Eu acho que as escolhas precisam ser consideradas estritamente do ponto de vista do interlocutor: o que o consumidor provavelmente precisará fazer?
E quais são as principais características de cada coleção?
- A tupla é acessada em ordem e imutável
- A lista é acessada em ordem e mutável
- O ditado é acessado por chave
A lista e a tupla são equivalentes para acesso, mas a lista é mutável. Bem, isso não importa para mim, se eu vou descompactar imediatamente os resultados:
score, top_player = play_round(players)
# or
idx, record = find_longest(records)
Não há nenhuma razão para eu me importar se é uma lista ou uma tupla, e a tupla é mais simples nos dois lados.
Por outro lado, se a coleção retornada for mantida inteira e usada como coleção :
points = calculate_vertices(shape)
points.append(another_point)
# Make a new shape
então pode fazer sentido que o retorno seja mutável. A homogeneidade também é um fator importante aqui. Digamos que você tenha escrito uma função para procurar padrões repetidos em uma sequência. As informações que recebo são o índice na sequência da primeira instância do padrão, o número de repetições e o próprio padrão. Esses não são os mesmos tipos de coisa. Mesmo que eu possa manter as peças juntas, não há razão para querer alterar a coleção . Isto não é um list
.
Agora para o dicionário.
o último cria um código mais legível porque você nomeou saídas
Sim, ter chaves para os campos torna os dados heterogêneos mais explícitos, mas também vêm com alguns ônus. Mais uma vez, no caso de "apenas vou descompactar as coisas", isso
round_results = play_round(players)
score, top_player = round_results["score"], round_results["top_player"]
(mesmo que você evite cadeias literais para as chaves), é um trabalho desnecessário em comparação com a versão da tupla.
A questão aqui é tríplice: quão complexa é a coleção, por quanto tempo a coleção será mantida unida e precisaremos usar esse mesmo tipo de coleção em vários lugares diferentes?
Eu sugiro que um valor de retorno de acesso com chave comece a fazer mais sentido do que uma tupla quando houver mais de três membros e, especialmente, onde houver aninhamento:
shape["transform"]["raw_matrix"][0, 1]
# vs.
shape[2][4][0, 1]
Isso leva à próxima pergunta: a coleção deixará esse escopo intacto, longe da chamada que o criou? O acesso com chave por lá ajudará absolutamente a compreensão.
A terceira pergunta - reutilização - aponta para um tipo de dados personalizado simples como uma quarta opção que você não apresentou.
A estrutura é de propriedade exclusiva dessa função? Ou você está criando o mesmo layout de dicionário em muitos lugares? Muitas outras partes do programa precisam operar nessa estrutura? Um layout de dicionário repetido deve ser fatorado para uma classe. O bônus é que você pode anexar um comportamento: talvez algumas das funções que operam nos dados sejam encapsuladas como métodos.
Uma quinta opção boa e leve é namedtuple()
. Essa é essencialmente a forma imutável do valor de retorno do dicionário.