[Python-es] matriz de matrices irregulares en longitud

Jesús Curbelo Rodríguez jescurbelo en gmail.com
Mie Abr 25 17:12:23 CEST 2012


Hola a todos,

     Hace tiempo escribí esto, igual te sirve aunque falta pulirlo.

Saludos.

#!/usr/bin/env python
# -*- coding: utf-8 -*-


class Vector(list):
     '''Vector de tamaño fijo con/sin comprobación de tipo'''

     def __new__(cls, *args, **kwargs):
         # Internamente los elementos del vector se almacenan en una lista.
         return list.__new__(cls, *args, **kwargs)

     def __init__(self, length, default_value=None, initial_values=None, 
typed=True):
         # El vector tendrá el tamaño indicado por length.
         # Los elementos del vector se inicializan con los elementos de 
initial_values.
         # Si len(initial_values) < length el vector se rellena con 
default_value
         # hasta alcanzar la longitud requerida.
         # Si len(initial_values) > length se descartan los elementos de 
initial_values
         # con indice mayor a length.
         # Si todos los elementos de initial_values y default_value 
tienen el mismo
         # tipo el vector será de dicho tipo y solo podra almacenar 
valores de
         # ese tipo. En caso contrario el vector no tendra tipo y podra 
almacenar
         # elementos de cualquier tipo.
         # Si typed == False no se tendra en cuenta el tipo de los 
elementos.

         try:
             same_type = True
             l = len(initial_values)
             for i in range(length):
                 if i < l:
                     self.append(initial_values[i])
                     same_type = same_type and (type(default_value) == 
type(initial_values[i]))
                 else:
                     self.append(default_value)
         except:
             self.extend([default_value]* length)
         finally:
             self.__length = length
             self.__type = type(default_value) if (same_type and typed) 
else type(None)


     def __setitem__(self, index, value):
         # Comprobamos el tipo antes de insertar un elemento.
         if self.__type == type(value) or self.__type == type(None):
             super(Vector, self).__setitem__(index, value)
         else:
             # Elemento de tipo incorrecto, no se inserta.
             raise ValueError

     def __setslice__(self, i, j, sequence):
         # Impedimos este método para que altere el tamaño del vector.
         # TODO: hacer lo mismo con el resto de métodos de la clase list que
         # pueden cambiar el tamaño del vector.
         raise ValueError # FIXME: poner la excepción correcta.

     def __count__(self):
         return self.__length

     @property
     def type(self):
         return self.__type

     @property
     def length(self):
         return self.__length


class Matrix(Vector):
     '''Matriz bidimensional de tamaño fijo con/sin comprobación de tipo'''

     def __init__(self, cols, rows, default_value=None, 
initial_values=None, typed=True):
         # Indicamos el número de columnas y filas de la matriz.
         self.__cols = cols
         self.__rows = rows
         super(Matrix, self).__init__(cols * rows, default_value, 
initial_values, typed)

     def __setitem__(self, index, value):
         # FIXME: interceptar índices no válidos.
         col, row = index
         index = self.__cols * row + col
         super(Matrix, self).__setitem__(index, value)

     def __getitem__(self, index):
         # FIXME: interceptar índices no válidos.
         col, row = index
         index = self.__cols * row + col
         return super(Matrix, self).__getitem__(index)

     def __repr__(self):
         result = ""
         for i in range(0, self.length, self.cols):
             result += "[%s]" % ", ".join([str(s) for s in self[i: i + 
self.cols]])
         return "[%s]" % result

     def __str__(self):
         result = ""
         for i in range(0, self.length, self.cols):
             result += "%s\n" % "  ".join([str(s) for s in self[i: i + 
self.cols]])
         return result

     @property
     def cols(self):
         return self.__cols

     @property
     def rows(self):
         return self.__rows

     def row(self, index):
         '''Devuelve la fila con índice index'''
         # FIXME: comprobar limites
         i = index * self.__cols
         return self[i:i + self.__cols]

     def col(self, index):
         '''Devuelve la columna con índice index'''
         # FIXME: comprobar limites
         return [self[index, i] for i in range(self.__cols)]

     def submatrix(self, ix, iy, jx, jy):
         '''Devuleve una submatrix de la matrix'''
         m = []
         for y in range(iy, jy + 1):
             k = y * self.__cols
             m.append(self[k + ix:k + jx + 1])
         # OJO!! el valor devuelto es un lista y no de la clase matrix
         return m

     def list(self):
         '''Devuleve los elementos de la matrix como una lista'''
         return list(self)

     def sublist(self, ix, iy, jx, jy):
         '''Devuleve una submatrix de la matrix en forma de lista'''
         l = []
         for y in range(iy, jy + 1):
             k = y * self.__cols
             l.extend(self[k + ix:k + jx + 1])
         # OJO!! el valor devuelto es un lista y no de la clase matrix
         return l

def main():
     a = Vector(10, 5,[])
     a[3] = 4
     print a
     b = Vector(15, 2, [x for x in range(10)], False)
     print b
     print b.length
     print b.type
     b[1] = 'a'
     print b
     m = Matrix(3, 3, 0)
     m[0, 0] = 1
     m[1, 0] = 2
     m[2, 0] = 3
     m[0, 1] = 4
     m[1, 1] = 5
     m[2, 1] = 6
     m[0, 2] = 7
     m[1, 2] = 8
     m[2, 2] = 9
     print m
     print repr(m)
     x, y = 1, 1
     print "item[%d, %d]: % d" % (x, y, m[x, y])
     print "total items: %d" % len(m)
     row = m.row(0)
     print "row[0]: ", row
     col = m.col(0)
     print "col[0]: ", col
     submatrix = m.submatrix(0,0,1,1)
     print "submatrix[0,0][1,1]: ", submatrix
     print 1 in submatrix
     print 11 in submatrix
     print m.list()
     sublist = m.sublist(0,0,1,1)
     print "sublist[0,0][1,1]: ", sublist
     print 1 in sublist
     print 11 in sublist
     m2 = Matrix(4,4, 1, [1,2,3,4], False)
     print m2
     print m2.length
     print m2.type

if __name__ == '__main__':
     main()
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://mail.python.org/pipermail/python-es/attachments/20120425/52ea343b/attachment.html>


Más información sobre la lista de distribución Python-es