Esto siempre me ha confundido. Parece que esto sería mejor:
my_list = ["Hello", "world"]
print(my_list.join("-"))
# Produce: "Hello-world"
Que esto:
my_list = ["Hello", "world"]
print("-".join(my_list))
# Produce: "Hello-world"
¿Hay alguna razón específica por la que es así?
-
declara que se está uniendo a una lista y convirtiendo a una cadena. Está orientada a resultados.str
que implementarla en cada tipo iterable.Respuestas:
Se debe a que se puede unir cualquier iterable (por ejemplo, list, tuple, dict, set), pero el resultado y la "unión" deben ser cadenas.
Por ejemplo:
Usar algo más que cadenas provocará el siguiente error:
fuente
list.join(string)
Parece más un enfoque orientado a objetos, mientras que mestring.join(list)
parece mucho más procedimental.print(str.join('-', my_list))
y funciona, se siente mejor.__iter__
método. Requerir que todos los iterables también se implementenjoin
complicaría una interfaz general (que también cubre iterables sobre no cadenas) para un caso de uso muy particular. La definiciónjoin
de los pasos secundarios de este problema a costa de la orden "no intuitiva". Una mejor opción podría haber sido mantener una función con el primer argumento como iterable y el segundo (opcional) como la cadena de unión, pero ese barco ha navegado.Esto se discutió en los métodos de String ... finalmente el hilo en Python-Dev se logró, y fue aceptado por Guido. Este hilo comenzó en junio de 1999 y
str.join
se incluyó en Python 1.6, que se lanzó en septiembre de 2000 (y era compatible con Unicode). Python 2.0 (str
métodos compatibles incluidosjoin
) se lanzó en octubre de 2000.str.join(seq)
seq.join(str)
seq.reduce(str)
join
como una función incorporadalist
s,tuple
s, sino todas las secuencias / iterables.seq.reduce(str)
Es difícil para los recién llegados.seq.join(str)
introduce dependencia inesperada de secuencias a str / unicode.join()
como función incorporada solo admitiría tipos de datos específicos. Por lo tanto, usar un espacio de nombres incorporado no es bueno. Sijoin()
admite muchos tipos de datos, crear una implementación optimizada sería difícil, si se implementa utilizando el__add__
método, entonces es O (n²).sep
) no debe omitirse. Explícito es mejor que implícito.No hay otras razones ofrecidas en este hilo.
Aquí hay algunos pensamientos adicionales (los míos y los de mi amigo):
La decisión de Guido se registra en un correo histórico , decidiendo sobre
str.join(seq)
:fuente
Porque el
join()
método está en la clase de cadena, en lugar de la clase de lista?Estoy de acuerdo en que se ve divertido.
Ver http://www.faqs.org/docs/diveintopython/odbchelper_join.html :
fuente
string
biblioteca Python 3 ha eliminado todos losstr
métodos redundantes , por lo que ya no puede usarlosstring.join()
. Personalmente, nunca pensé que fuera 'gracioso', tiene mucho sentido, ya que puedes unirte a mucho más que solo listas, ¡pero el carpintero siempre es una cadena!Estoy de acuerdo en que es contradictorio al principio, pero hay una buena razón. Unirse no puede ser un método de una lista porque:
En realidad, hay dos métodos de unión (Python 3.0):
Si unirse era un método de una lista, entonces tendría que inspeccionar sus argumentos para decidir a cuál de ellos llamar. Y no puedes unir byte y unir, por lo que la forma en que lo tienen ahora tiene sentido.
fuente
¡Esto se debe a que
join
es un método de "cadena"! Crea una cadena de cualquier iterable. Si atascamos el método en las listas, ¿qué pasa cuando tenemos iterables que no son listas?¿Qué pasa si tienes una tupla de cuerdas? Si este fuera un
list
método, ¡tendría que convertir cada iterador de cadenas comolist
antes para poder unir los elementos en una sola cadena! Por ejemplo:Vamos a rodar nuestro propio método de unión de lista:
Y para usarlo, tenga en cuenta que primero tenemos que crear una lista de cada iterable para unir las cadenas en ese iterable, desperdiciando memoria y poder de procesamiento:
Entonces vemos que tenemos que agregar un paso adicional para usar nuestro método de lista, en lugar de solo usar el método de cadena incorporado:
Advertencia de rendimiento para generadores
El algoritmo que Python usa para crear la cadena final con
str.join
realmente tiene que pasar dos veces sobre el iterable, por lo que si le proporciona una expresión generadora, primero debe materializarlo en una lista antes de que pueda crear la cadena final.Por lo tanto, aunque pasar generadores suele ser mejor que las listas de comprensión,
str.join
es una excepción:Sin embargo, la
str.join
operación sigue siendo semánticamente una operación de "cadena", por lo que aún tiene sentido tenerla en elstr
objeto que en varios iterables.fuente
Piense en ello como la operación ortogonal natural para dividir.
Entiendo por qué es aplicable a cualquier cosa iterable y, por lo tanto, no se puede implementar fácilmente solo en la lista.
Para facilitar la lectura, me gustaría verlo en el lenguaje, pero no creo que sea realmente factible: si la iterabilidad fuera una interfaz, podría agregarse a la interfaz, pero es solo una convención y, por lo tanto, no hay una forma central de agréguelo al conjunto de cosas que son iterables.
fuente
Principalmente porque el resultado de a
someString.join()
es una cadena.La secuencia (lista o tupla o lo que sea) no aparece en el resultado, solo una cadena. Como el resultado es una cadena, tiene sentido como método de una cadena.
fuente
-
en "-". join (my_list) declara que está convirtiendo a una cadena de elementos de unión en una lista. Está orientado a resultados. (solo para facilitar la memoria y la comprensión)Hago una exhaustiva hoja de trucos de métodos_de_cadena para su referencia.
fuente
Ambos no son agradables.
string.join (xs, delimit) significa que el módulo de cadena es consciente de la existencia de una lista, de la cual no tiene ningún conocimiento, ya que el módulo de cadena solo funciona con cadenas.
list.join (delimit) es un poco mejor porque estamos tan acostumbrados a que las cadenas sean un tipo fundamental (y lingüísticamente hablando, lo son). Sin embargo, esto significa que la unión debe enviarse dinámicamente porque en el contexto arbitrario de
a.split("\n")
compilador de Python, es posible que no sepa qué es y tendrá que buscarlo (de forma análoga a la búsqueda de Vtable), lo cual es costoso si lo hace mucho veces.si el compilador de tiempo de ejecución de Python sabe que la lista es un módulo integrado, puede omitir la búsqueda dinámica y codificar la intención en el código de bytes directamente, mientras que de lo contrario debe resolver dinámicamente la "unión" de "a", que puede estar en varias capas de herencia por llamada (ya que entre llamadas, el significado de unirse puede haber cambiado, porque python es un lenguaje dinámico).
lamentablemente, este es el último defecto de la abstracción; No importa qué abstracción elija, su abstracción solo tendrá sentido en el contexto del problema que está tratando de resolver, y como tal nunca podrá tener una abstracción consistente que no se vuelva inconsistente con las ideologías subyacentes a medida que comience a pegarlas. juntos sin envolverlos en una vista que sea consistente con su ideología. Sabiendo esto, el enfoque de Python es más flexible ya que es más barato, depende de usted pagar más para que se vea "más agradable", ya sea haciendo su propio envoltorio o su propio preprocesador.
fuente
Las variables
my_list
y"-"
son ambos objetos. Específicamente, son instancias de las claseslist
ystr
, respectivamente. Lajoin
función pertenece a la clasestr
. Por lo tanto, la sintaxis"-".join(my_list)
se usa porque el objeto"-"
se tomamy_list
como entrada.fuente