Tic Tac Toe in Python practice I'm quite novice here so apologies for any silly mistake in advance
I've been writing a simple tic tac toe game which is a part of my course in udemy
Since this is my first project, I want to do my best in order to learn new things besides learning how to code better. Generally, I want to optimize my code as much as possible.
Can anyone help me with this?
# Tic Tac Toe
# 17 July 2020

import os

test_board = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
player_input_num = 0    # numbers of inputs entered by player
player_num = 0
won = False
marker = 'X'


def clear_screen():
    os.system(&quot;clear&quot;)


def display_board(board_cords):
    '''
    display the board
    board_cords = list(left to right from top to bottom)
    '''
    line = '-'*40
    for counter in range(0, len(board_cords), 3):
        print(&quot;\t|\t\t|&quot;)
        print(
            f&quot;{board_cords[counter]}\t|\t{board_cords[counter+1]}\t|\t{board_cords[counter+2]}&quot;)
        print(line)
        counter += 3    # go to next row


def check_player_input(number):
    if number &lt; 10 and number &gt;= 0:  # checking the range
        return True
    else:
        print('Sorry the input is not in range [0-9] .')
        return False


def player_input(player_in):
    '''
    Executing codes on the previously checked input
    '''
    global player_input_num  # access to player_input_num
    if player_input_num &gt;= 2:
        # check if the position is free to use
        if check_capacity(test_board, player_in):
            result = place_marker(test_board, 'X', player_in)
            clear_screen()
            display_board(result)

            if check_win(test_board, marker):
                print(&quot;You Won!&quot;)
                global won
                won = True
        else:
            print(&quot;The current position is occupied.&quot;)
    else:
        if check_capacity(test_board, player_in):
            result = place_marker(test_board, 'X', player_in)
            clear_screen()
            display_board(result)
            player_input_num += 1
        else:
            print(&quot;The current position is occupied.&quot;)


def check_capacity(board, position):
    '''
    Check if the current position is free to use.
    '''
    return board[position] == ' '


def place_marker(board, marker, position):
    '''
    Replace the position with a marker
    '''
    board[position] = marker
    return board


def check_win(board, marker):
    '''
    Check if the current game is finished
    '''
    if board[0] == board[1] == board[2] == marker:
        return True
    if board[0] == board[3] == board[6] == marker:
        return True
    if board[0] == board[4] == board[8] == marker:
        return True
    if board[2] == board[5] == board[8] == marker:
        return True
    if board[6] == board[7] == board[8] == marker:
        return True
    if board[2] == board[4] == board[6] == marker:
        return True
    return False


def wanna_play():
    '''
    Check whether the players wanna play again or not.
    '''
    answer = input(&quot;Wanna play again? (Y or N)&quot;)
    return answer


# Main
display_board(test_board)
while True:
    while won == False:
        try:  # checking if input is int
            player_num = int(input(&quot;Enter a position: &quot;))   # casting into int
        except:
            print(&quot;Input is not a number&quot;)
            continue

        if check_player_input(player_num):
            player_input(player_num)

    if wanna_play() in ['y', 'Y', 'n', 'N']:
        print(&quot;something&quot;)
    else:
        print(&quot;Invalid input.&quot;)
        # print(&quot;Thanks for playing :)&quot;)



Edited.
First thing, I assume that you don't like to use Object Oriented concepts and we will continue by the function approach.
One thing that I should say to you about the comments is always to use them but in a meaningful way. Adding # Variables comment above of the variables will not add any additional value to your code. It only wastes space.
The second thing is about naming. You should always follow your chosen naming rules.
So it's better to use player_input_num or player_in_num instead of the playerin_num. That's more snake_case.
So the beginning of your program will be like this after doing the above things:
import os

test_board = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
player_input_num = 0

Acording to the comment rule we said above, you can remove the clear_screen docstring:
def clear_screen():
    os.system(&quot;clear&quot;)

Now we can take a look at the display_board function. You've used the while loop heare. But in the Python and for this case, using the for loop is more convient and readable. First, let's see the code:
def display_board(board_cords):
    '''
    display the board
    board_cords = list(left to right from top to bottom)
    '''
    line = '-'*40
    for i in range(0, len(board_cords), 3):
        print(&quot;\t|\t\t|&quot;)
        print(f&quot;{board_cords[i]}\t|\t{board_cords[i + 1]}\t|\t{board_cords[i + 2]}&quot;)
        print(line)

The i is the loop counter variable. We said that the loop should start counting from the zero until reaching the len(board_cords). And also we told that after each iteration, it should increase the i value by 3.
The next function is check_player_input. In this function, we can remove the syntax variable. Also, we can use a more pythonic way of checking the user input range.
def check_player_input():
    &quot;&quot;&quot;
    Gets an integer between 0 and 10 and calls `player_input` by that
    &quot;&quot;&quot;
    while True:
        try:
            temp = int(input(&quot;Enter a position: &quot;))
            if 0 &lt;= temp &lt; 10:
                break
            else:
                print('Sorry the input is not in range [0-9].')
        except:
            print(&quot;Input is not a number&quot;)
    player_input(temp)

Why removing the syntax variable is better? Because it's a variable with no real use. The original code is an infinite loop with a redundant variable.
Now we can go to the player_input function. The function that has an unnecessary global value.
One of the most famous **Not To Do` rules of software development is to avoid global values as possible. How we can avoid using that global value? The best way for doing that is to get the global value as an input parameter. But here I don't do that (Stay tuned for knowing why. For now, we just remove it and keeping its place).
The second problem here is the documentation of this function is not sufficient. I mean, what are the &quot;codes&quot;? You should add an extra description here for helping people understanding what is going on.
def player_input(player_in):
    if player_input_num &gt;= 2:
        while check_win(test_board) == False:
            result = place_marker(test_board, 'X', player_in)
            clear_screen()
            display_board(result)
            check_player_input()

        print(&quot;You Won!&quot;)
    else:
        while player_input_num &lt;= 2:
            result = place_marker(test_board, 'X', player_in)
            clear_screen()
            display_board(result)
            player_input_num += 1
            check_player_input()

In the next function, you did a very good thing. Inputting the board instead of using global values. I don't do it in your code in this post, but I strongly recommend doing that in other places of your code.
Doing that makes your code cleaner, more readable, more testable, and less buggy.
In the check_win there is a big problem. The login is too long and unreadable. It's better to break the logic down.
def check_win(board):
    if board[0] == board[1] == board[2]:
        return True
    if board[0] == board[3] == board[6]:
        return True
    if board[0] == board[4] == board[8]:
        return True
    if board[2] == board[5] == board[8]:
        return True
    if board[6] == board[7] == board[8]:
        return True
    if board[2] == board[4] == board[6]:
        return True
    return False

Why we did that? There are 6 different conditions for winning. So it's better to divide them from each other. So the person who reads your code can understand them more quickly.
All the things I've said until now are good, but there is a problem here. The code doesn't work.
The first problem is the player_input_num  value. In the original code, we only allow the user for inputting 3 values. So, What if the game will not finish after 3 moves? We should continue getting the inputs from the user until he/she wins the game.
We can change the player_input function like this:
def player_input(player_in):
    result = place_marker(test_board, 'X', player_in)
    clear_screen()
    display_board(result)
    if check_win(test_board, 'X'):
        print(&quot;You won&quot;)
    else:
        check_player_input()

We should change the check_win function too. Additional to the previous conditions, we should check that all 3 cell values are equal to the marker.
def check_win(board, marker):
    if board[0] == board[1] == board[2] == marker:
        return True
    if board[0] == board[3] == board[6] == marker:
        return True
    if board[0] == board[4] == board[8] == marker:
        return True
    if board[2] == board[5] == board[8] == marker:
        return True
    if board[6] == board[7] == board[8] == marker:
        return True
    if board[2] == board[4] == board[6] == marker:
        return True
    return False

Here it is. But still, we had a problem. What if the all cells of the board has been filled? We can add a new function for checking if the game has finished or not. But we can do it now because for doing that, you should have two players with two different markers. And I think you can do that by yourself.
For avoiding mistakes, I leave all the codes we seen above here. I hope this help you (Don't forget that it's not the best program for doing what you wanted, but I think, for now, it is a acceptable one).
import os

test_board = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']


def clear_screen():
    '''
    clearing the screen
    '''
    os.system(&quot;clear&quot;)


def display_board(board_cords):
    '''
    display the board
    board_cords = list(left to right from top to bottom)
    '''
    line = '-'*40
    for i in range(0, len(board_cords), 3):
        print(&quot;\t|\t\t|&quot;)
        print(f&quot;{board_cords[i]}\t|\t{board_cords[i + 1]}\t|\t{board_cords[i + 2]}&quot;)
        print(line)


def check_player_input():
    &quot;&quot;&quot;
    Gets an integer between 0 and 10 and calls `player_input` by that
    &quot;&quot;&quot;
    while True:
        try:
            temp = int(input(&quot;Enter a position: &quot;))
            if 0 &lt;= temp &lt; 10:
                break
            else:
                print('Sorry the input is not in range [0-9].')
        except:
            print(&quot;Input is not a number&quot;)
    player_input(temp)


def player_input(player_in):
        result = place_marker(test_board, 'X', player_in)
        clear_screen()
        display_board(result)
        if check_win(test_board, 'X'):
            print(&quot;You won&quot;)
        else:
            check_player_input()

def place_marker(board, marker, position):
    board[position] = marker
    return board


def check_win(board, marker):
    if board[0] == board[1] == board[2] == marker:
        return True
    if board[0] == board[3] == board[6] == marker:
        return True
    if board[0] == board[4] == board[8] == marker:
        return True
    if board[2] == board[5] == board[8] == marker:
        return True
    if board[6] == board[7] == board[8] == marker:
        return True
    if board[2] == board[4] == board[6] == marker:
        return True
    return False


if __name__ == &quot;__main__&quot;:
    display_board(test_board)
    check_player_input()

Two other things: 1. your logic for winning is not complete. 2. search about the if __name__ == &quot;__main__&quot;:, it's better to use that.