Leer Archivos Binarios en Python
En la entrada anterior vimos como abrir y manejarnos con archivos de texto. Pero como hago para leer archivos binarios. Bien para este propósito necesitaremos usar el modulo struct. Y la estructura binaria del archivo que queremos leer.
Bien a modo de ejemplo yo pondré un programita en C que genere un archivo binario simple y luego un script python que levante este archivo y lo imprima en pantalla.
Programita en C es muy simple, solo genera el archivito.
#include <stdio.h> struct rec { int x; char y; int z; }; int main() { char i; FILE *f; struct rec r; f=fopen("prueba.bin","wb"); if (!f) return 1; for (i=1;i<=20; i++) { r.x = i; r.y = i; r.z = i + 1; fwrite(&r,sizeof(struct rec),1,f); printf ("(%i,%i,%i)\n",r.x,r.y,r.z); } fclose(f); printf("Peso de la estructura rec %i\n", sizeof(struct rec)); return 0; }
En mi caso el compilador C que usa como minimo una palabra de 32 bit (4 bytes) para la escritura, por eso cada registro rec pesa 12 bytes. 4 del primer int 1 del char , otros 4 del segundo int y 3 mas que usa para completar el char.
El ejemplo en python se puede ver en readBin.py
#!/usr/bin/python # Nombre de Fichero : readBin.py import struct f = file('prueba.bin','r') i=1 f.seek(0,2) #vamos al final del archivo fin = f.tell() f.seek(0,0) #vamos al principio del archivo while (f.tell() < fin): s = f.read(12) dato = str(struct.unpack("i b i", s)) # desempaquetamos print i ," ->",dato i+=1;
Mascara de struct
Lo que sigue es una traducción de print struct.__doc__
Como opción podemos indicar en el formato de la mascara, el primer char byte que indica el orden, el tamaño y la alineación:
@: native order, tamaño y la alineación (default)
=: native order, std. tamaño y la alineación
<: little-endian, std. tamaño y la alineación
>: big-endian, std. tamaño y la alineación
!: es igual que >
Los demás caracteres indican los tipos de los datos atómicos del registro que utilizaremos y debe coincidir exactamente.
x: pad byte (no data); c:char; b:signed byte; B:unsigned byte;
h:short; H:unsigned short; i:int; I:unsigned int;
l:long; L:unsigned long; f:float; d:double.
Casos especiales (decimal contar anterior indica la longitud):
s: cadena (array de char); p: cadena de pascal.
Un caso especial (sólo disponible en formato nativo):
P: Un tipo que es lo suficientemente amplia como para celebrar un puntero.
Un caso especial (no en modo nativo a menos que ‘long long’ en la plataforma C):
q: largo tiempo; Q: unsigned long long
El espacio en blanco entre los formatos se ignora.
La variable struct.error es una excepción planteada por los errores.
Archivos en Python
Python no s facilita la función open que recibe dos argumentos y nos devuelve un objeto tipo file. El primer argumento es el nombre del archivo en formato string, el segundo también en formato string es el modo de acceso al archivo. Esto podrá ser “r” para lectura, “w” para escritura.
Algunos ejemplos de apertura de archivo podria ser:
f = open(“archivo.txt”,”w”)
f = open(“archivo.txt”,”r”)
Algunos de los metodos y propiedades del objeto file son:
Propiedades
- closed: nos devuelve true si esta cerrado y false si esta abierto el archivo
- fileno: nos retorna el Descriptor del archivo.
- mode: retorna el modo con el que esta abierto el archivo
- name: retorna el nombre del archivo
Métodos
- close: lo invocaremos siempre que terminemos de usar el archivo.
- next: trae el siguiente valor del archivo.
- read: le la cantidad de bytes que se le pasa por parámetro, si no se le pasa parámetro le todo el archivo
- readline: le una línea del archivo
- readlines: le la cantidad de líneas que le pasamos por parámetro y nos la devuelve en una lista de strings.
- seek: nos mueve por el archivo.
- tell: nos dice la posición en la que estamos del archivo
- truncate: trunca el archivo
- write: escribe el archivo
- xreadlines: devuelve una matriz con todas sus lineas (“disen por hay que se discontinuara en la versión 3.0 de python”)
Un ejemplo de generacion de un archivo de texto y luego otro ejemplo que le ese archivo seria fileT1.py y fileT2.py
#!/usr/bin/python # Nombre de Fichero : fileT1.py f = open("arch.txt","w") f.write("Esto es un archivo de texto\n"); f.write("Generado con python\n"); f.write("no es hermoso\n") f.close()
y ahora a leerlo
#!/usr/bin/python # Nombre de Fichero : fileT1.py f = open("arch.txt","r") print f.readline(), # le la primer linea print f.read(29), # le los siguientes 29 bytes print f.read(2), # le los siguientes 2 bytes print f.next() # le todos los bytes desde donde esta hasta el final f.close()
Otra forma de leer el archivo podria aver sido con xreadlines que lo ejemplificamos en xreadlines.py
#!/usr/bin/python # Nombre de Fichero : xreadlines.py f = open("arch.txt","r") for i in f.xreadlines(): print i, f.close()
Un ejemplo del contador de palabras que no pretende ser ilustrativo sino simplemente mostrar lo que se puede hacer en una line con python 😉 . Aca va cuentaPalabras.py
#!/usr/bin/python # Nombre de Fichero : cuentaPalabras.py import string; f = open("arch.txt","r") print reduce(lambda x , y : x + len(y.split()), [0] + f.readlines()) f.close()
Un lindo ejemplo de manejo de archivos lo pone LuAuF en http://luauf.com/2008/04/07/python-gestion-de-archivos/ en el ejemplo veran como leer la información ID3 tag de un MP3
Lambda en python
Me gusto mucho la explicación de lambda de la wikipedia:
“El cálculo lambda es un sistema formal diseñado para investigar la definición de función, la noción de aplicación de funciones y la recursión. Fue introducido por Alonzo Church y Stephen Kleene en la década de 1930; Church usó el cálculo lambda en 1936 para resolver el Entscheidungsproblem. Puede ser usado para definir de manera limpia y precisa qué es una «función computable». El interrogante de si dos expresiones del lambda cálculo son equivalentes no puede ser resuelto por un algoritmo general. Esta fue la primera pregunta, incluso antes que el problema de la parada, para el cual la indecidibilidad fue probada. El cálculo lambda tiene una gran influencia sobre los lenguajes funcionales, como Lisp, ML y Haskell.
Se puede considerar al cálculo lambda como el más pequeño lenguaje universal de programación. Consiste en una regla de transformación simple (sustitución de variables) y un esquema simple para definir funciones.
El cálculo lambda es universal porque cualquier función computable puede ser expresada y evaluada a través de él. Por lo tanto, es equivalente a las máquinas de Turing. Sin embargo, el cálculo lambda no hace énfasis en el uso de reglas de transformación y no considera las máquinas reales que pueden implementarlo. Se trata de una propuesta más cercana al software que al hardware.”[ http://es.wikipedia.org/wiki/C%C3%A1lculo_Lambda%5D
Lambda es el feacture con el cual podremos ejecutar funciones anónimas. Es decir funciones sin ningún nombre.
La sintaxis de lambda en python es:
lambda :
lambda <aParameterList> : <a Python expression using the parameters>
por ejemplo
Los ejemplos de la entrada de programación funcional con lambda quedarían:
lambda y map:
Ejemplo:
#!/usr/bin/python # Nombre de Fichero : map_lambda.py lt = range(5) print lt print map (lambda x:x + 1,lt) print lt
lambda y filter:
Ejemplo:
#!/usr/bin/python # Nombre de Fichero : filter_lambda.py lt = range(5) print lt print map (lambda x:x in (1,3,6),lt) #como ya sabemos manejar map ;-). print filter (lambda x:x in (1,3,6),lt) print lt
lambda y reduce:
Ejemplo:
#!/usr/bin/python # Nombre de Fichero : reduce.py lt = range(5) lts = ["hola ","como ","estas."] print " lt -> %s"%lt print " lts -> %s" %lts print " reduce lt -> %s" %reduce (lambda x,y : x+y,lt) print " reduce lts -> %s" %reduce (lambda x,y : x+y,lts)
–
Programación funcional en python
Para empezar a entrar en tema podríamos ver la wikipedia
Los programas escritos en un lenguaje funcional están constituidos únicamente por definiciones de funciones, entendiendo éstas no como subprogramas clásicos de un lenguaje imperativo, sino como funciones puramente matemáticas, en las que se verifican ciertas propiedades como la transparencia referencial (el significado de una expresión depende únicamente del significado de sus subexpresiones), y por tanto, la carencia total de efectos laterales.
Otras características propias de estos lenguajes son la no existencia de asignaciones de variables y la falta de construcciones estructuradas como la secuencia o la iteración (lo que obliga en la práctica a que todas las repeticiones de instrucciones se lleven a cabo por medio de funciones recursivas).
Existen dos grandes categorías de lenguajes funcionales: los funcionales puros y los híbridos. La diferencia entre ambos estriba en que los lenguajes funcionales híbridos son menos dogmáticos que los puros, al admitir conceptos tomados de los lenguajes imperativos, como las secuencias de instrucciones o la asignación de variables. En contraste, los lenguajes funcionales puros tienen una mayor potencia expresiva, conservando a la vez su transparencia referencial, algo que no se cumple siempre con un lenguaje funcional híbrido.”
[http://es.wikipedia.org/wiki/Programaci%C3%B3n_funcional]
Python nos facilita un conjunto de feature que nos permite darle un enfoque funcional a nuestra programación. Estos feacture son:
- map
- filter
- reduce
- lambda
- listas por comprensión
Map:
La función “map” es una función de orden superior, que recibe en su primer parámetro una función fx y en su segundo parámetro una lista lt. Y lo que hará simplemente es aplicar la función fx a los elementos de la lista lt.
Ejemplo:
#!/usr/bin/python # Nombre de Fichero : map.py lt = range(5) def fx(x): return x + 1 print lt print map (fx,lt) print lt
Filter:
La función “filter” es una función de orden superior, que recibe en su primer parámetro una función fx que retorne true o false y en su segundo parámetro una lista lt. Y lo que hará simplemente es aplicar la función fx a los elementos de la lista lt y retornar una lista con todos los elementos que dieron trae.
Ejemplo:
#!/usr/bin/python # Nombre de Fichero : filter.py lt = range(5) def fx(x): return x in (1,3,6) print lt print map (fx,lt) #como ya sabemos manejar map print filter (fx,lt) print lt
Reduce:
La función “reduce” es una función de orden superior, que recibe en su primer parámetro una función fx y una lista lt. Pero su funcionamiento es menos evidente que «map» y «filter», ya que lo que devuelve es un solo elemento. Para verlo mas claro veamos el ejemplo.
Ejemplo:
#!/usr/bin/python # Nombre de Fichero : reduce.py lt = range(5) lts = ["hola ","como ","estas."] def sumatoria(x,y): return x+y print " lt -> %s"%lt print " lts -> %s" %lts print " reduce lt -> %s" %reduce (sumatoria,lt) print " reduce lts -> %s" %reduce (sumatoria,lts) print " lt -> %s"%lt print " lts -> %s" %lts
En las próximas entradas explicaremos listas por comprensión y lambda.
Diccionarios en Python
Los diccionarios en Python son como los Arrays Asociativo de cualquier otro lenguaje. Se diferencian de las listas ya los diccionarios son indexados por claves. Las claves solo podrán ser de algún tipo de dato inmutable como los números, los strings, las tuplas…
En otras palabras un diccionario es in conjunto de pares clave-valor donde la clave es inmutable y el valor es cualquier cosa.
Para ver un poco los diccionarios jugaremos en el intérprete de python.
Un diccionario vació se define:
>>> d={} >>> type (d) <type 'dict'>
Un diccionario precargado se define:
>>> d={"Nombre":"Arturo Elias","Apellido":"Anton"} >>> type (d) <type 'dict'>
Se accede a cada uno de los valores:
>>> d={"Nombre":"Arturo Elias","Apellido":"Anton"} >>> d["Nombre"] 'Arturo Elias' >>> d["Apellido"] 'Anton' >>>
Obtengo la lista de claves:
>>> d={"Nombre":"Arturo Elias","Apellido":"Anton"} >>> d.keys() ['Nombre', 'Apellido']
Obtengo la lista de todos los valores del diccionario:
>>> d={"Nombre":"Arturo Elias","Apellido":"Anton"} >>> d.values() ['Arturo Elias', 'Anton']
Elimina todos los elementos del diccionario:
>>> d.clear() >>> d {}
Concatena dos diccionarios:
>>> d={"Nombre":"Arturo Elias","apellido":"Anton"} >>> d {'Nombre': 'Arturo Elias', 'apellido': 'Anton'} >>> d.update({"direccion":"pepiri 318"}) >>> d {'Nombre': 'Arturo Elias', 'apellido': 'Anton', 'direccion': 'pepiri 318'} >>>
Saber si la clave esta en el diccionario:
>>> d={"Nombre":"Arturo Elias","apellido":"Anton"} >>> d.has_key("Nombre") True >>> d.has_key("Edad") False >>>
Un ejemplo de cómo recorrer un diccionario se pude ver en diccionario.py:
#!/usr/bin/python # Nombre : diccionario.py d={"Nombre":"Arturo Elias","apellido":"Anton"} for key in d.keys(): print "%s -> %s"%(key,d[key])
dara una salida
>>> Nombre -> Arturo Elias apellido -> Anton >>>
Tuplas en Python
Una tupla es una lista se va a poder modificar después de haberla creado.
Las tuplas se definen como las listas salvando que en lugar de encerrarlas entre corchetes se encierran entre paréntesis.
Los índices de las tuplas empiezan en 0 e índices negativos empiezan a contar desde el final de la lista.
Formas de recorrer una tupla y el manejo de índices podemos ver en tupla1.py
#!/usr/bin/python # Nombre de Fichero : tupla1.py tupla = (1,[2,3,4],2,"Pedro"); for r in tupla: print str(r) print "----------------------------" for i in range(len(tupla)): print str(i),"->",str(tupla[i]) print "----------------------------" print "El ultimo elemento de la tupla es %s" % tupla[-1] print "----------------------------" print "Una tupla el segundo y tercer", print "elemento de la tupla original %s" % str(tupla[1:3]) print "Los tres ultimos elementos %s" % str(tupla[1:])
Si bien las tuplas no se pueden modificar las tuplas se pueden trasformar a listas por medio del método list y las listas se pueden trasformar a tuplas por medio del método tuple.
Para ilustrar esto pondré un extracto de mi interprete python, con la salida del programa anterior
1 [2, 3, 4] 2 Pedro ---------------------------- 0 -> 1 1 -> [2, 3, 4] 2 -> 2 3 -> Pedro ---------------------------- El ultimo elemento de la tupla es Pedro ---------------------------- Una tupla el segundo y tercer elemento de la tupla original ([2, 3, 4], 2) Los tres ultimos elementos ([2, 3, 4], 2, 'Pedro') >>> list(tupla) [1, [2, 3, 4], 2, 'Pedro'] >>> tuple(list(tupla)) (1, [2, 3, 4], 2, 'Pedro')
La ventaja de las tuplas contra las listas es que las tuplas son más rápidas
Encapsulamiento en python
La idea de encapsulamiento segun Grady Booch es
«La abstracción y el encapsulamiento son conceptos complementarios: la abstracción se centra en el comportamiento observable de un objeto, mientras el encapsulamiento se centra en la implementación que da lugar a este comportamiento. El encapsulamiento se consigue a menudo mediante la ocultación de información, que es el proceso de ocultar todos secretos de un objeto que no contribuyen a sus caracteristicas esenciales; típicamente, la estructura de un objeto esta oculta, así como la implementación de sus metodos.»[Análisis y diseño orientado a objetos con aplicaciones *]
En otras palabras es impedir el acceso al los métodos o variables del objeto, para que solo se puedan usar dentro de la instancia del objeto. Esto en los lenguajes como Java o C# lo logran con unos modificadores de acceso (anteponen a la definición del método o propiedad public, private, protected, etc.).
Los modificadores de acceso permiten al diseñador de clases delimitar la frontera entre lo que es accesible para los usuarios de la clase, lo que es estrictamente privado y ‘no importa’ a nadie más que al diseñador de la clase e incluso lo que podría llegar a importar a otros diseñadores de clases que quisieran alterar, completar o especializar el comportamiento de la clase.
Python no cuenta con estos modificadores de acceso para lograr el encapsulamiento. Por que el acceso a una variable o método viene dado por su nombre. Para que un método sea privado en Python lo que hay que hacer es anteponerle dos guiones bajos “__” antes del nombre y no dejar que termine con dos guiones bajos “__”. Lo mismo para las variable.
Un ejemplo se vera en encapsulacion.py
#!/usr/bin/env python # Nombre de Fichero : encapsulacion.py class Persona(object) : "Calse Persona" def __init__(self, pNombre,pEdad,pSueldo) : self.setNombre(pNombre) self.setEdad(pEdad) self.__setSueldo(pSueldo); def setEdad(self, pEdad) : self.__edad = pEdad def getEdad(self) : return self.__edad def setNombre(self, pNombre) : self.__nombre = pNombre def getNombre(self) : return self.__nombre def __setSueldo(self,pSueldo): self.__sueldo = pSueldo def getSueldo(self): return self.__sueldo nombre = property(getNombre, setNombre) edad = property(getEdad, setEdad) class Gerente(Persona) : def __init__(self, pNombre,pEdad): Persona.__init__(self, pNombre,pEdad,5000) class Secretaria(Persona) : def __init__(self, pNombre,pEdad) : Persona.__init__(self, pNombre,pEdad,500) if __name__ == '__main__': g = Gerente("Mariano", 56) s = Secretaria("Rocio", 33) print "El Gerente es", g.nombre , " gana ", g.getSueldo() print "La Secretaria es ", s.getNombre(), " gana ",s.getSueldo()
Veran que la clase Persona hereda de object esto es asi por que tiene que usar propiedades.
También varan que el objeto «g» imprime su nombre por medio de su propiedad.
*ISBN 968 444 3528 Editorial Pearson
Polimorfismo en Python
El lenguaje Python soporta el polimorfismo de forma muy cómoda, ya que al ser de tipado dinámico deja que el programador pase cualquier objeto como parámetro de un método.
En otras palabras, si el método le envía un mensaje que el objeto no entiende, el mensaje dará error en el tiempo de ejecución y no en tiempo de diseño.
El polimorfismo es cuando dos o más objetos entienden los mismos mensajes (métodos).
Un ejemplo de esto lo daremos en polimorfismo.py
#!/usr/bin/python # Nombre de Fichero : polimorfismo.py class Gato: "Clsase Gato" def __init__(self): self.pos = 0 def trepar(self): pass def caminar(self): self.pos = self.pos + 10 def maullar(self): print "Miu Miu" class Perro: "Clase Perro" def __init__(self): self.pos = 0 def caminar(self): self.pos = self.pos +4 def ladrar(self): print "Gua Gua" def pasearMascota(mascota): for i in range(5): mascota.caminar() print "La mascota quedo en " + str(mascota.pos) perro=Perro() gato=Gato() pasearMascota(perro) pasearMascota(gato)
La salida de este programa no dará error aunque le pase distintos parámetros al proceso pasearMascota ya que los dos saben caminar.
El resultado que dará será.
>>> La mascota quedo en 20 La mascota quedo en 50
Observé que los objetos perro y gato son polimorficos en el método caminar, pero no en los métodos maullar y ladrar