2012-06-29 6 views
21

Estoy usando Python desde algunas veces y estoy descubriendo la forma "pitonica" de codificar. Estoy usando muchas tuplas en mi código, la mayoría de ellas son posiciones polares o cartesianas.Legibilidad de Tuplas: [0,0] vs (0,0)

me encontré escribiendo esto:

window.set_pos([18,8]) 

en lugar de esto:

window.set_pos((18,8)) 

para deshacerse de la doble paréntesis encontré difícil de leer.

Parece que python realiza automáticamente la conversión de tipo de lista a tupla, ya que mi código funciona correctamente.

¿Pero es una buena forma de codificar? ¿Tiene algún consejo de presentación que pueda usar para escribir un código legible?

Gracias de antemano por sus respuestas seguramente esclarecedoras.

+0

Me gusta la forma en que lo ha escrito, parece más bien definido. – jamylak

+9

Python no está "haciendo una conversión de tipo de lista a tupla". Esto es [pato escribiendo] (http://en.wikipedia.org/wiki/Duck_typing) en acción: presumiblemente 'window.set_pos' requiere una secuencia de dos elementos, pero no necesariamente un 2-'tuple' (digo presumiblemente ya que no sé de dónde viene 'window.set_pos' o qué hace). – Chris

+9

Vuelva a escribir la función para tomar dos argumentos en lugar de uno 2-tuple. –

Respuesta

25

Tendría cuidado al decidir evitar tuplas a favor de listas en todas partes. ¿Alguna vez ha utilizado el módulo dis? Observen lo que Python está haciendo a nivel de código de bytes cuando se hace una lista versos haciendo una tupla:

>>> def f(): 
...  x = [1,2,3,4,5,6,7] 
...  return x 
... 
>>> def g(): 
...  x = (1,2,3,4,5,6,7) 
...  return x 
... 
>>> import dis 
>>> dis.dis(f) 
    2   0 LOAD_CONST    1 (1) 
       3 LOAD_CONST    2 (2) 
       6 LOAD_CONST    3 (3) 
       9 LOAD_CONST    4 (4) 
      12 LOAD_CONST    5 (5) 
      15 LOAD_CONST    6 (6) 
      18 LOAD_CONST    7 (7) 
      21 BUILD_LIST    7 
      24 STORE_FAST    0 (x) 

    3   27 LOAD_FAST    0 (x) 
      30 RETURN_VALUE  
>>> 
>>> 
>>> dis.dis(g) 
    2   0 LOAD_CONST    8 ((1, 2, 3, 4, 5, 6, 7)) 
       3 STORE_FAST    0 (x) 

    3   6 LOAD_FAST    0 (x) 
       9 RETURN_VALUE 

A pesar de que probablemente nunca será un problema en una aplicación de interfaz gráfica de usuario (como su ejemplo parece ser), por razones de rendimiento Es posible que desee tener cuidado al hacerlo en cualquier lugar de su código.

+1

Muchas gracias, ¡me convenciste! Realmente me importa el rendimiento ya que mi aplicación no es una GUI sino un juego con una GUI gráfica. Su respuesta detallada de bytecode es realmente útil para entender lo que sucede en segundo plano (no conocía el módulo de dis). –

+1

Acabo de sincronizar las dos funciones: la versión de la lista tarda aprox. el doble de tiempo que la versión de tupla (2.1 vs 0.9 segundos para 10 millones de llamadas). Para colecciones de dos elementos, sin embargo, las diferencias son menores: 1.6 vs. 0.9 segundos. –

+2

Ah, claro - Olvidé que los literales de tuplas están [plegados] (http://stackoverflow.com/a/8068248/577088). Si pasa literales (y no tuplas construidas a partir de variables), esto podría marcar una gran diferencia. – senderle

0

Si desea hacer hincapié en el hecho de que el parámetro es una tupla, puede convertir explícitamente que:

window.set_pot(tuple([18, 18])) 
+4

Esto se ve mucho peor. – jamylak

4

OMI la única ventaja de usar (18,8) sobre [18,8] es que un objeto tupla es inmutable y usted puede asegúrese de que no se cambie dentro de la función que se pasa, mientras que [18,8] se puede cambiar fácilmente.

4

Python no realiza ninguna conversión automática de list a tuple, a menos que el método set_pos lo haga explícitamente. tupla y lista tienen protocolos muy similares, por lo que tienden a ser intercambiables dentro de ese protocolo. Todavía puede romper cosas, en particular porque la tupla es inmutable y puede ser hasheada, y una lista no lo es.

Para responder a su pregunta, apenas escriben

window.set_pos((18,18)) 

espacios adecuados hacen milagros con estilo de codificación.

+4

PEP-8 aconseja NO hacer esto: http://www.python.org/dev/peps/pep-0008/#pet-peeves – jamylak

+1

@jamylak: estoy de acuerdo, y estoy de acuerdo con la sugerencia de PEP, pero este es un especial caso que puede valer la excepción. –

+0

@jamylak No se aplica según el idioma, lo que significa que es solo un estilo de codificación que le gusta a los autores de Python. No es el único estilo de codificación, y nunca debería tomarse como tal. Simplemente mírelos como "buenas pautas", y prepárese para romperlos cuando dañen la legibilidad, como en este caso. – Izkata

12

Usted dice

Parece que pitón está haciendo de forma automática la conversión del tipo de la lista de tupla

Eso es dudosa. Dado que las listas y las tuplas son sequence types, ambas implementan muchos de los mismos comportamientos, y la biblioteca de GUI que esté utilizando no necesita ninguno de los comportamientos de solo lista.

Es probablemente bien para hacer esto en muchos casos, pero tenga en cuenta que las listas toman un poco más de espacio que las tuplas:

>>> sys.getsizeof((1, 2)) 
72 
>>> sys.getsizeof([1, 2]) 
88 

y puede ser más lenta que las tuplas en algunas cosas:

>>> lst, tup = [1, 2], (1, 2) 
>>> def unpack(x): 
...  a, b = x 
...  
>>> %timeit unpack(tup) 
10000000 loops, best of 3: 163 ns per loop 
>>> %timeit unpack(lst) 
10000000 loops, best of 3: 172 ns per loop 

Estos son muy pequeñas diferencias que no importará hasta llegar a escalas mucho más grandes - como en mil millones de llamadas - s o el intercambio podría valer la pena.

Aún así, no veo que la gente haga esto muy a menudo. Parece un buen truco de legibilidad, pero podría tener consecuencias inesperadas en algunas circunstancias. Por ejemplo, si pasa una lista que intenta usar nuevamente más tarde, debe tener cuidado de no modificarla dentro de la función. Finalmente, como correctamente señala J.F. Sebastian, las tuplas y las listas tienden a significa cosas ligeramente diferentes; usarlos de formas no convencionales podría negar el impulso de legibilidad que buscas.

+0

¡Gracias por su respuesta precisa! Sé que puede parecer un poco extraño, pero estoy encantado con la idea de usar un objeto inapropiado solo para fines de legibilidad. Mi método "set_pos" simplemente descomprime el argumento en dos variables, pero se usa la mayor parte del tiempo dentro de un ciclo y me preocupan los problemas de rendimiento. ¿Importan mucho las 14 ns? –

+0

No, 14ns no importará en absoluto cuando se trata de establecer la posición de su ventana. –

8

Tengo serias dudas de que las tuplas contra las listas hagan una diferencia notable en el rendimiento en su caso. No haga micro-optimizaciones a menos que su generador de perfiles lo diga. La legibilidad es una prioridad.

list y tuple son ambos sequence types.

Semánticamente pueden ser preferibles las tuplas (consulte Tuples have structure, lists have order). La posición es un solo objeto que tiene atributos x, y.

Visualmente las listas pueden ser más fáciles de leer en este caso.

Elija lo que elija solo sea consistente.

Compruebe si window soporta los siguientes:

window.pos = 18, 8 

Una posible manera de ponerla en práctica es hacer que el pos un property y se unen set_pos() como colocador.

+2

+1 para la semántica de las listas de tuplas vs., que casi siempre debe ser el factor decisivo para usar. – FogleBird

Cuestiones relacionadas