Search code examples
pythonpython-3.xreturn-type

Function will not return a value after it calls itself


I just started learning Python a few days ago. I'm working on a chess game, and what I'm having trouble with is the code that determines the position of the piece the player wants to play. If I input a string with two numbers in it, the function parses them out and assigns them and the y and x value.

However, if only one or no numbers are found in the string, it prints "No digits or not enough digits found", lets you re-enter a string, and calls the function again. My problem is that after it calls itself, if you put in a valid string, it will identify the numbers, package it into a list like it's supposed to, but then won't return anything. I checked to make sure that the list is properly filled, and it is, it just returns none.

Here is the error:

Traceback (most recent call last):
  File "C:\Users\Jack\PycharmProjects\Messing With 2D Lists\Messing With 2D Lists.py", line 91, in <module>
    piece_num = position[0]
TypeError: 'NoneType' object is not subscriptable

Here is the code that calls the function, and the final line is the one that is triggering the error, because instead of a list it's receiving a none type:

posit = input("Choose your piece\nEnter coordinates: ")

position = piece_position(posit)

print(position)

piece_num = position[0]

Here is the "chess board" in case you want to reproduce my error because it's referenced in the code.

chess = [
    [1, 2, 1, 2, 1, 2, 1, 2],
    [2, 1, 2, 1, 2, 1, 2, 1],
    [1, 2, 1, 2, 1, 2, 1, 2],
    [2, 1, 2, 1, 2, 1, 2, 1],
    [1, 2, 1, 2, 1, 2, 1, 2],
    [2, 1, 2, 1, 2, 1, 2, 1],
    [1, 2, 1, 2, 1, 2, 1, 2],
    [2, 1, 2, 1, 6, 1, 2, 1],

]

And here is the function that determines the piece position:

def piece_position(pos):
    
    num1d = False
    num2d = False

    for char in pos:
        if not num1d:
            if char.isdigit():
                num1 = int(char) - 1
                num1d = True
            else:
                pass
        elif not num2d:
            if char.isdigit():
                num2 = int(char) - 1
                num2d = True
            else:
                pass

    print(num1d)
    print(num2d)

    if num1d and num2d:
        print(num1, num2)
        result = [chess[num1][num2]]
        result.append(num1)
        result.append(num2)
        print(result)
        return result
    else:
        print("No digits or not enough digits found")
        posit2 = input("Choose your piece\nEnter coordinates: ")
        piece_position(posit2)

Also I know that I call it as posit2 when it flips instead of just posit, and the variable is asking for the result of posit, but it doesn't seem to make any difference whether I change it to posit or posit2.

Feel free to make constructive organizational criticisms, again I'm brand new to Python and still figuring it out, I know I have lots to improve and lots I don't understand.


Solution

  • You'll get None in the else statement that repeats the function, which you could return the function call result, or you could just use a while loop

    def piece_position(pos):
        
        num1d = False 
        num2d = False
    
        while not num1d and not num2d:
            for char in pos:
                if not num1d:
                    if char.isdigit():
                        num1 = int(char) - 1
                        num1d = True
                elif not num2d:
                    if char.isdigit():
                        num2 = int(char) - 1
                        num2d = True
            if not num1d and not num2d:
                pos = input("Try again:") 
                num1d = False 
                num2d = False
    
        result = []
        #... 
        return result
    

    Or, possibly simpler would be doing the same outside the function body rather than within (this way is definitely simpler to test)

    pos = input("Enter coordinates") 
    result = piece_position(pos)
    while not result:  # assuming this returned None, or an empty list, for example 
        pos = input("Enter coordinates") 
        result = piece_position(pos)