Isso sempre me confundiu. Parece que isso seria melhor:
my_list = ["Hello", "world"]
print(my_list.join("-"))
# Produce: "Hello-world"
Do que isso:
my_list = ["Hello", "world"]
print("-".join(my_list))
# Produce: "Hello-world"
Existe uma razão específica para ser assim?
-
declara que você está ingressando em uma lista e convertendo em uma string.str
que implementá-la em todos os tipos iteráveis.Respostas:
É porque qualquer iterável pode ser associado (por exemplo, lista, tupla, ditado, conjunto), mas o resultado e o "marceneiro" devem ser cadeias de caracteres.
Por exemplo:
Usar algo diferente de strings gerará o seguinte erro:
fonte
list.join(string)
parece mais uma abordagem orientada a objetos, enquanto mestring.join(list)
parece muito mais processual.print(str.join('-', my_list))
e funciona, se sente melhor.__iter__
método. Exigir que todos os iterables também implementemjoin
complicaria uma interface geral (que também abrange iterables sobre não-strings) para um caso de uso muito particular. A definiçãojoin
de strins evita esse problema ao custo da ordem "não intuitiva". Uma escolha melhor poderia ter sido manter uma função, com o primeiro argumento sendo iterável e o segundo (opcional) sendo a sequência de marcadores - mas esse navio navegou.Isso foi discutido nos métodos String ... finalmente encadeados no Python-Dev achive, e foi aceito por Guido. Esse encadeamento começou em junho de 1999 e
str.join
foi incluído no Python 1.6, lançado em setembro de 2000 (e com suporte a Unicode). O Python 2.0 (str
incluindo métodos suportadosjoin
) foi lançado em outubro de 2000.str.join(seq)
seq.join(str)
seq.reduce(str)
join
como uma função embutidalist
s,tuple
s, mas todas as seqüências / iteráveis.seq.reduce(str)
é difícil para os novatos.seq.join(str)
introduz dependência inesperada de seqüências para str / unicode.join()
como uma função interna suportaria apenas tipos de dados específicos. Portanto, usar um espaço para nome interno não é bom. Sejoin()
suportar muitos tipos de dados, seria difícil criar uma implementação otimizada, se implementada usando o método__add__
método, será O (n²).sep
) não deve ser omitida. Explícito é melhor que implícito.Não há outros motivos oferecidos neste segmento.
Aqui estão alguns pensamentos adicionais (meus e dos meus amigos):
A decisão de Guido é registrada em um correio histórico , decidindo
str.join(seq)
:fonte
Como o
join()
método está na classe string, em vez da classe list?Eu concordo que parece engraçado.
Consulte http://www.faqs.org/docs/diveintopython/odbchelper_join.html :
fonte
string
biblioteca Python 3 removeu todos osstr
métodos redundantes , para que você não possa mais usá-lostring.join()
. Pessoalmente, nunca achei "engraçado", faz todo o sentido, pois você pode participar de muito mais do que apenas listas, mas o marceneiro é sempre uma string!Concordo que é contra-intuitivo no começo, mas há uma boa razão. A junção não pode ser um método de lista porque:
Na verdade, existem dois métodos de junção (Python 3.0):
Se a junção fosse o método de uma lista, ele teria que inspecionar seus argumentos para decidir qual deles chamar. E você não pode unir byte e str, então o modo como eles o fazem agora faz sentido.
fonte
Isso ocorre porque
join
é um método "string"! Ele cria uma string a partir de qualquer iterável. Se colocamos o método nas listas, e quando temos iterables que não são listas?E se você tiver uma tupla de strings? Se esse fosse um
list
método, você teria que converter todos os iteradores de strings como alist
antes de poder juntar os elementos em uma única string! Por exemplo:Vamos lançar nosso próprio método de junção de lista:
E, para usá-lo, observe que precisamos primeiro criar uma lista de cada iterável para unir as strings nessa iterável, desperdiçando tanto a memória quanto o poder de processamento:
Então, vemos que precisamos adicionar uma etapa extra para usar nosso método de lista, em vez de apenas usar o método de string incorporado:
Advertência de desempenho para geradores
O algoritmo que o Python usa para criar a sequência final
str.join
precisa passar pela iterável duas vezes; portanto, se você fornecer uma expressão de gerador, precisará materializá-la em uma lista antes de poder criar a sequência final.Assim, embora distribuir geradores geralmente seja melhor do que a compreensão de lista,
str.join
é uma exceção:No entanto, a
str.join
operação ainda é semanticamente uma operação "string", por isso ainda faz sentido tê-la nostr
objeto do que em iterables diversos.fonte
Pense nisso como a operação ortogonal natural a ser dividida.
Entendo por que é aplicável a qualquer coisa iterável e, portanto, não pode ser facilmente implementado apenas na lista.
Para facilitar a leitura, eu gostaria de vê-lo na linguagem, mas não acho que seja realmente viável - se a iterabilidade fosse uma interface, ela poderia ser adicionada à interface, mas é apenas uma convenção e, portanto, não há uma maneira central de adicione-o ao conjunto de coisas que são iteráveis.
fonte
Principalmente porque o resultado de a
someString.join()
é uma string.A sequência (lista ou tupla ou o que for) não aparece no resultado, apenas uma sequência. Como o resultado é uma sequência, faz sentido como método de uma sequência.
fonte
-
join "-". join (my_list) declara que você está convertendo para uma string de unir elementos a uma lista. É orientado a resultados. (apenas para facilitar a memória e o entendimento)Eu faço uma cheatsheet exaustiva de methods_of_string para sua referência.
fonte
Ambos não são bons.
string.join (xs, delimit) significa que o módulo de string está ciente da existência de uma lista, da qual não tem negócios, pois o módulo de string funciona apenas com strings.
list.join (delimit) é um pouco melhor porque estamos acostumados a que as strings sejam um tipo fundamental (e lingualmente falando, elas são). Entretanto, isso significa que a junção precisa ser despachada dinamicamente, porque no contexto arbitrário de
a.split("\n")
compilador python, talvez você não saiba o que é, e precisará procurá-la (analogicamente à pesquisa em vtable), o que é caro se você o fizer muitas vezes. vezes.se o compilador de tempo de execução python souber que a lista é um módulo interno, poderá ignorar a pesquisa dinâmica e codificar a intenção diretamente no bytecode, enquanto, caso contrário, precisará resolver dinamicamente a "junção" de "a", que pode estar em várias camadas de herança por chamada (já que, entre as chamadas, o significado de associação pode ter mudado, porque python é uma linguagem dinâmica).
infelizmente, essa é a derradeira falha da abstração; não importa qual abstração você escolher, sua abstração só fará sentido no contexto do problema que você está tentando resolver e, como tal, você nunca poderá ter uma abstração consistente que não se torne inconsistente com as ideologias subjacentes quando começar a colá-las. juntos, sem agrupá-los em uma visão que seja consistente com sua ideologia. Sabendo disso, a abordagem do python é mais flexível, uma vez que é mais barato, cabe a você pagar mais para torná-la "mais agradável", criando seu próprio wrapper ou seu próprio pré-processador.
fonte
As variáveis
my_list
e"-"
são ambos objetos. Especificamente, são instâncias das classeslist
estr
, respectivamente. Ajoin
função pertence à classestr
. Portanto, a sintaxe"-".join(my_list)
é usada porque o objeto"-"
está sendo usadomy_list
como entrada.fonte