Hello!
I'm studying Python and wrote a very simple class to work with bidimensional arrays - just as an exercise.
Before writing te class I played around with functions and they worked fine.
When I tried to do the same using a class, things became strange...
Okay, I wrote this class:

import random

class Matriz:
	
	matriz = []

	def __init__ (self, grau_matriz, inicio):
	
		self.__grau_matriz = grau_matriz
		
		if inicio == 0:
			self.zero()
		elif inicio == 1:
			self.aleatoria()

	def zero(self):

		for i in range(self.__grau_matriz):
			linha = []
			for j in range(self.__grau_matriz):
				linha.append(0)
                
		self.matriz.append(linha)
			
	def aleatoria(self):
		for i in range(self.__grau_matriz):
			linha = []
			for j in range(self.__grau_matriz):
				linha.append(random.randrange( 1, 10 ))
				
                
		self.matriz.append(linha)

	def mostra(self):
		for i in range(self.__grau_matriz):
			for j in range(self.__grau_matriz):
				print "%2d " % self.matriz[i][j],
			print

		print

To teste this class, I wrote this;

# Use Matriz class

from Matriz import Matriz

matriz1 = Matriz(3,0) 

matriz1.mostra()
print

And the result is "IndexError: list index out of range" in mostra method, when it tries to run this line: print "%2d " % self.matriz[j],

I ask, why??

So far I did not find where I did it wrong.

Thanks very much for any hints! :)

Dani AI

Generated

Good catch, — the IndexError you saw is exactly the kind of symptom produced when only one row ever gets appended while the display code expects n rows. That indentation bug (append outside the outer loop) leaves self.matriz shorter than self.__grau_matriz, so indexing past the single row raises the error.

A couple of further points worth adding so the class is more robust:

  • Make matriz an instance attribute, not a class attribute. Declaring matriz = [] at class level shares the same list across all instances, which causes subtle cross-instance bugs. Put self.matriz = [] in __init__.
  • Prefer list comprehensions to build the full grid in one expression, or ensure the append happens inside the outer loop. Beware of the common pitfall [[0]*n]*n — that creates n references to the same row, so changing one element changes every row.

A compact, modern pattern that avoids these traps:

import random

class Matriz:
    def __init__(self, n, mode='zeros'):
        self.n = n
        if mode == 'zeros':
            self.matriz = [[0 for _ in range(n)] for _ in range(n)]
        elif mode == 'random':
            self.matriz = [[random.randint(1, 9) for _ in range(n)] for _ in range(n)]
        else:
            self.matriz = []

    def __str__(self):
        return '\n'.join(' '.join(f"{v:2d}" for v in row) for row in self.matriz)

Final tips: test with two instances to confirm no sharing (e.g., mutate m1.matriz[0][0] and verify m2 is unchanged), and use print(m) (Python 3) or print m (Python 2) depending on the interpreter — implementing __str__ makes output consistent across calls.

Hello!
Well... aham... I found the bug.

The line in which I appended the values to the array was outside the for. Hence the index out of range error message.

The for structure should read, then:

def zero(self):
		for i in range(self.grau_matriz):
			linha = []
			for j in range(self.grau_matriz):
				linha.append(0)
                
			self.matriz.append(linha)

This is valid for both methods in which I use the same idea...

Thanks! :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.