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