Es¿Qué tan bueno es startswith?
text.startswith('a')
mejor que
text[0]=='a'
?
Conocer el texto no está vacío y solo nos interesa el primer carácter del mismo.
Es¿Qué tan bueno es startswith?
text.startswith('a')
mejor que
text[0]=='a'
?
Conocer el texto no está vacío y solo nos interesa el primer carácter del mismo.
Estoy de acuerdo con los demás que comienzan con es más legible, y deberías usar eso. Dicho esto, si el rendimiento es un gran problema para un caso tan especial, punto de referencia es:
$ python -m timeit -s 'text="foo"' 'text.startswith("a")'
1000000 loops, best of 3: 0.537 usec per loop
$ python -m timeit -s 'text="foo"' 'text[0]=="a"'
1000000 loops, best of 3: 0.22 usec per loop
Así es text[0]
amost 2,5 veces más rápido - pero es una operación bastante rápido; ahorrarías ~ 0.3 microsegundos por comparación, dependiendo del sistema. Sin embargo, a menos que esté haciendo millones de comparaciones en una situación crítica en cuanto al tiempo, seguiría con los comienzos más legibles.
text[0]
falla si text
es una cadena vacía:
IronPython 2.6 Alpha (2.6.0.1) on .NET 4.0.20506.1
Type "help", "copyright", "credits" or "license" for more information.
>>> text = ""
>>> print(text.startswith("a"))
False
>>> print(text[0]=='a')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: index out of range: 0
EDIT: Usted dice que "sabe" que text
no está vacío ... ¿cuánta confianza tiene de eso, y lo que usted quiere que suceda si es es vacío en la realidad? Si una falla es apropiada (por ejemplo, significa un error en su código) que fomentaría el uso de text[0]=='a'
.
Otras preguntas:
¿Cuánto le preocupa sobre el rendimiento de esto? Si esto es crítico para el rendimiento, compárelo con en su tiempo de ejecución específico de Python. No estaría por completo sorprendido al encontrar que (digamos) un formulario era más rápido en IronPython y uno diferente más rápido en CPython.
¿Qué usted (y su equipo) encuentra más legible?
Personalmente, yo diría que startswith
es más fácil de leer.
Además, a partir de Python 2.5 startwith
puede tomar una tupla de prefijos para buscar:
>>> "hello world".startswith(("hello","goodbye"))
True
Sí: es más fácil de usar y fácil de leer. Cuando está tratando de detectar más de una letra, cuando se utiliza el corte en lonchas, usted tiene que saber cuánto tiempo el texto de destino es:
haystack = 'Hello, World!'
needle = 'Hello'
# The easy way
result = haystack.startswith(needle)
# The slightly harder way
result = haystack[:len(needle)] == needle
Editar: La pregunta parece haber cambiado. Ahora dice: "saber que el texto no está vacío y que solo nos interesa el primer carácter". Eso lo convierte en una situación hipotética bastante sin sentido.
Sospecho que el que pregunta está tratando de "optimizar" su código para la velocidad de ejecución. Si ese es el caso, mi respuesta es: no. Use la forma que sea más legible y, por lo tanto, más fácil de mantener cuando tenga que regresar y trabajar en ella dentro de un año. Optimice solo si el perfil muestra que la línea de código es el cuello de botella. Este no es un algoritmo O (n²). Es una comparación de cuerdas.
La pregunta es realmente acerca de probar la primera letra. – dugres
He encontrado este problema exacto en un caso de uso no hipotético; de hecho, tenía una asignación que se refería a un diccionario si solicitabas una clave que comenzaba con ~, y otro diccionario para cada otro carácter. Se llamó decenas de miles o millones de veces y, en particular, se solicitó que se volvieran a dibujar las partes sucias de una ventana cuando un mouse se movía sobre ella (una columna modelo de lista virtual GTK +), por lo que necesitaba ser extremadamente eficiente. Como no sabía que la cadena no estaba vacía, utilicé [: 1]; como se sugiere a continuación, todavía era dos veces más rápido que startsWith. –
La frase estándar para el questiom es: "La optimización prematura es la raíz de todo mal".
Entonces, ¿cuál usarías? – dugres
text.startswith ('a'). Indica claramente lo que quieres lograr. Solo puedo pensar en el texto [0] == 'a' como una alternativa, como una forma de ahorrar algunos ciclos de CPU. – Zed
Presupuesto selectivo. Lea todo el párrafo en el que está incrustada esa cláusula. Ni siquiera es una oración completa en el original. – EJP
texto [0] == 'a' es bueno teniendo en cuenta el rendimiento. También necesita agregar validación cuando usa esto.
text[0]
pueden fallar pero el equivalente text[:1]
es seguro si la cadena está vacía.
Si quiere comparar más de un carácter, creo que .startswith()
es mejor.
PEP 8 dice explícitamente para utilizar startswith
, debido a la legibilidad:
- Use ''.startswith() and ''.endswith() instead of string
rebanar para comprobar de prefijos o sufijos.
startswith() and endswith() are cleaner and less error prone. For example: Yes: if foo.startswith('bar'): No: if foo[:3] == 'bar':
def compo2():
n = "abba"
for i in range(1000000):
n[:1]=="_"
es más rápido que
def compo():
n = "abba"
for i in range(1000000):
n.startswith("_")
cprofile reporta 0,061 para compo2
en comparación con 0.954 para compo
en mi máquina. Esto es de interés en caso de que quiera hacer MUCHAS comprobaciones de prefijo para varias "_mystring". Si la mayoría de las cadenas no comienzan con guiones bajos, entonces usando string[:1]== char
antes de usar startswith
es una opción para optimizar su código. En una aplicación real, este método me ahorró aproximadamente el 15% del tiempo de la CPU.
Lo siento, no he dicho que sé que el texto no está vacío. – dugres
@Jon Skeet: Es cierto, pero eso puede suceder con decir 'text [: 1]' en su lugar. – balpha
@balpha: Pero esa es una pregunta diferente, entonces :) –