7
\$\begingroup\$

My code creates a "grid" of empty places, where 0 is used as the place holder, in a size specified by the user.

I was wondering if there were more efficient ways of doing this,or perhaps ways that make more aesthetically pleasing grids with less code.

My code is in working order and does as it says on the label, I also implemented a system that does not allow for incorrect inputs.

def gridSize_def():
    global gridSize
    while True:
        try:
            gridSize = int(input("input grid length and width\n"))
            if gridSize<2:
                print ("invalid int")
            else:
                break
        except ValueError:
            print ("invalid input") 
    grids = [[] for _ in range (gridSize)]
    for i in range(0,gridSize):
        grids[i-1]=[0 for _ in range(gridSize)]
    return grids

def grid_def():
    for i in range (0,gridSize):
        print (grids[i-1])

grids = gridSize_def()
grid_def()

All feedback welcome!

\$\endgroup\$

4 Answers 4

7
\$\begingroup\$

Grid creation

You know about list-comprehensions, but you use a default value before filling your rows with zeroes. You could do it in one go:

grids = [[0 for _ in range(gridSize)] for _ in range(gridSize)]

which can be simplified to

grids = [[0] * gridSize for _ in range(gridSize)]

Grid printing

The for loop in Python is meant to be used to iterate directly over elements rather than indices:

for row in grids:
    print(row)

Function parameters

It is bad practice to rely on global to share data accros functions. You should define those function to accept parameters instead.

This let you also extract input handling from your grid creation function which is also better as let you have a single responsibility per function:

def ask_size():
    while True:
        try:
            grid_size = int(input("input grid length and width\n"))
            if grid_size < 2:
                print ("invalid int")
            else:
                return grid_size
        except ValueError:
            print ("invalid input") 

def make_grid(size):
    return [[0] * size for _ in range(size)]

def print_grid(grid):
    for row in grid:
        print(row)


grids = make_grid(ask_size())
print_grid(grids)

Exception handling

Python have else clauses that are executed when the try part succeeded. The aim is to reduce the amount of code protected by the try to avoid catching unexpected exceptions. In your case, you could change that part to:

def ask_size():
    while True:
        try:
            grid_size = int(input("input grid length and width\n"))
        except ValueError:
            print ("invalid input") 
        else:
            if grid_size > 1:
                return grid_size
            print ("invalid int")
\$\endgroup\$
4
\$\begingroup\$

You are mixing camelCase with snake_case, this is a bad idea no matter what style you prefer (snake_case is recommended though).

Code that generates a grid is simple, following 3 lines of yours:

grids = [[] for _ in range (gridSize)]
for i in range(0,gridSize):
    grids[i-1]=[0 for _ in range(gridSize)]

Well, you could replace that with following line:

grids = [[0] * grid_size for _ in range(grid_size)]

Note that [[0] * grid_size] * grid_size looks even nicer but does thing you don't want from it (try it out to see the difference though)

Biggest part of your code is prompting user for input. I'd say that you should move that to a separate function. Something like ask_how_many(prompt, test=lambda x:True) - function that asks user the prompt message and gets input until it can be converted to int and until that value passes the test (optional).

That way, you'd be able to reuse user-prompting part. Also, grid-generating part would be only generating grid, having 1 responsibility (not 2, as it is now).

\$\endgroup\$
4
\$\begingroup\$

One could accomplish the creation of the grid/matrix using NumPy:

grid = numpy.zeros(shape=(4,4))

This question was tagged , hence my shape parameters. Those could easily be changed to the variables input by the user (which you should handle in a separate function).

Note that this will perform slower than the other presented solutions for smaller shape values. The speed improvement kicks in with larger sizes.

\$\endgroup\$
2
  • \$\begingroup\$ I have had some problems with using numpy, I am unsure if this is a thing you need to import or perhaps download? As a beginner I have not come across this before and so I apologise if this question has an obvious answer. \$\endgroup\$ Jul 13, 2016 at 9:34
  • \$\begingroup\$ @bubblezgopop You should install the numpy package with pip, and then import it into your code. \$\endgroup\$
    – syb0rg
    Jul 13, 2016 at 16:48
3
\$\begingroup\$

In standard python:

a = [[0 for _i in range(gridsize)] for _j in range(gridsize)]

You could use str.join for better printing:

def print_grid:
  for i in grid:
    print ("|| " + " | ".join(i) + " ||")

Also, there's a better way to check if the user inputs a non-integer: str.isdigit can be used to check if int can be called on the str.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.