2011-11-28 19 views
7

Soy un novato de Python que intenta analizar un archivo para crear una tabla de asignaciones de memoria. Mi archivo de entrada está en el siguiente formato:Diccionario de Python con variables como claves

48 bytes allocated at 0x8bb970a0 
24 bytes allocated at 0x8bb950c0 
48 bytes allocated at 0x958bd0e0 
48 bytes allocated at 0x8bb9b060 
96 bytes allocated at 0x8bb9afe0 
24 bytes allocated at 0x8bb9af60  

Mi primer objetivo es hacer una tabla que cuenta los casos de un determinado número de asignaciones de bytes. En otras palabras, mi salida deseada para la entrada anterior sería algo así como:

48 bytes -> 3 times 
96 bytes -> 1 times 
24 bytes -> 2 times 

(por ahora, no estoy preocupado por las direcciones de memoria)

Desde que estoy usando Python, pensé Hacer esto usando un diccionario sería el camino correcto (basado en aproximadamente 3 horas de lectura de tutoriales de Python). ¿Es eso una buena idea?

Al tratar de hacer esto usando un diccionario, decidí hacer del número de bytes la 'clave', y un contador como el 'valor'. Mi plan era incrementar el contador en cada aparición de la clave. A partir de ahora, mi fragmento de código es el siguiente:

# Create an empty dictionary 
allocationList = {} 

# Open file for reading 
with open("allocFile.txt") as fp: 
    for line in fp: 
     # Split the line into a list (using space as delimiter) 
     lineList = line.split(" ") 

     # Extract the number of bytes 
     numBytes = lineList[0]; 

     # Store in a dictionary 
     if allocationList.has_key('numBytes') 
      currentCount = allocationList['numBytes'] 
      currentCount += 1 
      allocationList['numBytes'] = currentCount 
     else 
      allocationList['numBytes'] = 1 

for bytes, count in allocationList.iteritems() 
    print bytes, "bytes -> ", count, " times" 

Con esto, me sale un error de sintaxis en el 'has_key' llame, que me lleva a la pregunta de si es posible incluso utilizar como variables claves del diccionario. Todos los ejemplos que he visto hasta ahora suponen que las claves están disponibles por adelantado. En mi caso, puedo obtener mis llaves solo cuando estoy analizando el archivo de entrada.

(Tenga en cuenta que mi archivo de entrada puede ejecutar en miles de líneas, con cientos de diferentes claves)

Gracias por cualquier ayuda que puede proporcionar.

+0

como veo que usted ha citado 'numBytes', por lo que, siempre se está haciendo referencia a la constante – dmitry

+0

y se omite en las líneas de colon después de 'si allocationList.has_key ('numBytes')' y 'else' - debe ser error de sintaxis – dmitry

Respuesta

10

Aprender un idioma es tanto acerca de la sintaxis y los tipos básicos como de la biblioteca estándar. Python ya tiene una clase que hace que tu tarea sea muy fácil: collections.Counter.

from collections import Counter 

with open("allocFile.txt") as fp: 
    counter = Counter(line.split()[0] for line in fp) 

for bytes, count in counter.most_common(): 
    print bytes, "bytes -> ", count, " times" 
+0

Siento que su respuesta es más cierta que la de nadie aquí –

+2

+1: Si solo está interesado en el recuento, 'Counter' es el camino a seguir. Por otro lado, el OP escribió: * por ahora, no me preocupan las direcciones de memoria * --- Supongo que tarde o temprano necesitará una solución personalizada que vaya más allá de 'Counter'. –

+0

Muchas gracias por esta solución. Lo intenté, pero no funcionó. Esto se debe a que Counter solo está disponible para Python> 2.7 y estoy usando 2.6.4. Pero me llevó a: http://stackoverflow.com/questions/3594514/how-to-find-most-common-elements-of-a-list, y aquí encontré una manera de resolver mi problema. Pero estoy marcando esta respuesta como la solución, porque esta es probablemente la mejor manera de resolver el problema. – Gautam

4

El método de dictionnary dict.has_key() tiene disappeared in python3, para reemplazarlo, utilice la palabra clave in:

if numBytes in allocationList: # do not use numBytes as a string, use the variable directly 
    #do the stuff 

Pero en su caso, también puede reemplazar todo el

if allocationList.has_key('numBytes') 
      currentCount = allocationList['numBytes'] 
      currentCount += 1 
      allocationList['numBytes'] = currentCount 
     else 
      allocationList['numBytes'] = 1 

con una línea con get:

allocationList[numBytes] = allocationList.get(numBytes, 0) + 1 
+2

No es necesario establecer el valor dos veces con 'setdefault'; use 'dict.get' en su lugar. –

+0

@FerdinandBeyer: tienes razón, fue un poco exagerado e inútil usar setdefault. –

+0

Se eliminó 'has_key' y se usó 'in'. Gracias por el consejo. Probablemente estaba leyendo algunos tutoriales obsoletos. – Gautam

1

Definitivamente puedes usar variables como claves dict. Sin embargo, tiene una variable llamada numBytes, pero está utilizando una cadena que contiene el texto "numBytes"; está utilizando una constante de cadena, no la variable. Eso no causará el error, pero es un problema. En su lugar, intente:

if numBytes in allocationList: 
    # do stuff 

Además, considere un Counter. Esta es una clase conveniente para manejar el caso que está viendo.

4

obtiene un error de sintaxis, porque se echa en falta los dos puntos al final de esta línea:

if allocationList.has_key('numBytes') 
            ^

Su enfoque está muy bien, pero podría ser más fácil de usar dict.get() con un valor por defecto:

allocationList[numBytes] = allocationList.get(numBytes, 0) + 1 

Dado que su allocationList es un diccionario y no una lista, es posible que desee elegir un nombre diferente para la variable.

+0

Gracias. No tenía ni idea sobre el ":". Acabo de descubrir que también necesito uno al final de mi declaración 'para'. – Gautam

Cuestiones relacionadas