2012-01-29 10 views
5

En Python, a menudo reutilizan variables en forma análoga a esto:en Python

files = files[:batch_size] 

me gusta esta técnica, ya que ayuda a cortar en el número de variables que necesito para realizar un seguimiento.

Nunca he tenido ningún problema pero me pregunto si me están perdiendo posibles inconvenientes, p. rendimiento, etc.

+0

No veo cuál es la pregunta aquí. ¿Cuál es la alternativa para comparar? Usando una segunda variable como 'files = XYZ; files_head = archivos [: batch_size] '? ¿Por qué debería haber alguna diferencia? –

+0

alternativa siendo algo así como: new_set_of_files = files [: batch_size] – jldupont

+0

Notarías la principal de inmediato: * ¡Oye! ¡Aún necesito ese viejo valor para 'archivos'! *. – Droogans

Respuesta

6

No hay inconvenientes técnicos para volver a utilizar nombres de variables. Sin embargo, si reutiliza una variable y cambia su "propósito", puede confundir a otros que leen su código (especialmente si pierden la reasignación).

En el ejemplo que proporcionó, sin embargo, se da cuenta de que en realidad está generando una lista completamente nueva cuando empalma. Hasta que el GC recolecte la copia anterior de esa lista, esa lista se almacenará en la memoria dos veces (excepto lo que se cortó). Una alternativa es iterar sobre esa lista y detenerse cuando llegue al elemento batch_size, en lugar de terminar la lista, o incluso más sucintamente, del files[batch_size:].

+0

+1 Un buen punto acerca de cómo puedes evitar crear un objeto nuevo (aunque quizás sea menos legible) – RoundTower

+1

@cheeken: Sin embargo, otra alternativa (probablemente la más pitonica) es crear un generador con 'itertools.islice'. –

+0

¡Buena llamada, @NiklasBaumstark! A quien haya votado negativamente: Agradecería un comentario explicando por qué para poder corregirlo. – cheeken

5

algo de información sobre ese ejemplo concreto: Si lo que desea es una iteración, mapa o filtrar el resultado, puede utilizar un generador para evitar una copia matriz:

import itertools 
files = itertools.islice(files, batch_size) 

Como para el caso general : Si asigna el nuevo valor a un nombre ya existente o a un nuevo nombre, no debería haber absolutamente ninguna diferencia (al menos desde el punto de vista del intérprete/VM). Ambos métodos producen casi exactamente el mismo código de bytes:

Python 2.7.2 (default, Nov 21 2011, 17:25:27) 
[GCC 4.6.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dis 
>>> def func1(files): 
... files = files[:100] 
... 
>>> def func2(files): 
... new_files = files[:100] 
... 
>>> dis.dis(func1) 
    2   0 LOAD_FAST    0 (files) 
       3 LOAD_CONST    1 (100) 
       6 SLICE+2    
       7 STORE_FAST    0 (files) 
      10 LOAD_CONST    0 (None) 
      13 RETURN_VALUE   
>>> dis.dis(func2) 
    2   0 LOAD_FAST    0 (files) 
       3 LOAD_CONST    1 (100) 
       6 SLICE+2    
       7 STORE_FAST    1 (new_files) 
      10 LOAD_CONST    0 (None) 
      13 RETURN_VALUE   

El mismo se puede observar en Python 3.

De hecho, func1 incluso podría ser un poco más rápido, porque el nombre files se ha visto antes y podría ya estar en algún caché de búsqueda variable.

+0

¿Puedo preguntarte qué diferencia va a hacer ese '1' diferente? –

+0

@Rik: Creo que es el índice de la variable local afectada ('0' en el primer caso, porque esta es la primera variable accedida,' 1' en el segundo caso). Aunque no estoy 100% seguro. –

1

Realmente no va a haber muchas desventajas al reutilizar variables, excepto que tampoco va a experimentar muchas ventajas. El Python GC va a tener que ejecutarse de todos modos para recopilar el objeto viejo, por lo que no hay una ganancia de memoria inmediata al anular la variable, a diferencia de los lenguajes compilados estáticamente como C, donde la reutilización de una variable impide la asignación de memoria por completo el nuevo objeto.

Además, realmente puede confundir a cualquier lector futuro de su código, que generalmente espera que los objetos nuevos tengan nombres nuevos (un subproducto de los lenguajes recogidos de basura).

1

La desventaja sería, que no se puede utilizar:

file_rest = files[batch_size:] 

En cuanto al rendimiento No hay ningún inconveniente. Por el contrario: incluso podrías mejorar el rendimiento al evitar la colisión hash en el mismo espacio de nombres.

Hubo un SO-post con respecto a esto en otro contexto.