Connect 4 on a 4×4 board in Python
Design

You've got the right diagnosis: your functions are poorly designed, such that it is unclear what their inputs and outputs are.  We definitely need to fix your functions so that they act the way functions should.  Redesigning the code to be object-oriented would not necessarily improve the code further, though.

Let's consider your main loop:


loop = True

while loop:
    check_def()
    confirmed()
    placement_def()
    checks_def()
    if not loop:
        break
    user_def()



Looking at just that code, I can't tell what your functions do.  I can't even tell that it's code for a board game.  Compare that to the main() function in my solution below:

def main():
    board = [
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
    ]
    print_board(board)
    for player in itertools.cycle([1, 2]):
        make_move(board, player)
        print_board(board)
        if is_winner(board, player):
            print("Player {0} has won".format(player))
            break
        if is_board_full(board):
            print("Board is full")
            break

if __name__ == '__main__':
    main()


This code makes it clear that it's a board game in which two players take turns making a move.  Each function has:


A purpose, and the name tells you what it does.  check_def doesn't mean anything, but is_winner does.  The fact that the name starts with "is_…" implies that it's a function that returns either True or False.
A useful return value.  If is_winner(…) returns True, then the if statement in the loop can use that information to end the game.  You don't want the information to be passed back indirectly by setting a global loop variable.
Inputs passed as parameters.  What information does is_winner(…) need to do its job?  Obviously, it needs to know the state of the board.  It's also helpful to know which player just moved, so that it only needs to consider the most recent player's coins.


To help enforce these good habits, you should write a docstring for every function that explains the purpose, the inputs, and the return value.

Bug

Your checks_def() function, which is intended to detect the end of the game, is buggy:


def checks_def():
    return check_def() and checkEmpty_def() and diagcheck_def()



check_def() (which detects horizontal and vertical wins) never returns True: it can either return False, or fall off the end of the function and implicitly return None.  Therefore, due to the way short-circuit evaluation works with the and operator, the code checkEmpty_def() (to detect a tie) and diagcheck_def() (to detect a diagonal win) will never be executed.

The logic in that line is further wrong in that you should check for diagonal wins before detecting that the board is full, because the last coin that fills the board might be a winning move.

Expressiveness

Python has some very powerful techniques to write loops with a lot less code.  In the solution below, my is_winner(…) and is_board_full(…) functions make use of the built-in functions all() and any() with generator expressions.

zip(*board) is a handy idiom for transposing row and columns.

Suggested solution

from itertools import cycle

def print_board(board):
    """
    Print the board.
    """
    print("\nCurrent board:")
    for row in reversed(board):
        print(row)

def make_move(board, player):
    """
    Ask the player for a column, and mark the move on the board if it is a
    legal move.  If it is an illegal move, ask again.
    """
    while True:
        try:
            c = -1 + int(input("Input a coin, player {0} (1-4): ".format(player)))
            if not (0 &lt;= c &lt; 4):
                print("Column number is out of range.")
            top_row = next(row for row in board if row[c] == 0)
            top_row[c] = player
            break
        except ValueError:
            print("Illegal move.")
        except StopIteration:
            print("This column is full.  Try another one!")

def is_winner(board, player):
    """
    Return True if a row, column, or diagonal consisting of four entries for
    the given player.
    """
    return (
        any(all(c == player for c in row) for row in board) or
        any(all(r == player for r in col) for col in zip(*board)) or
        (board[0][0] == board[1][1] == board[2][2] == board[3][3] == player) or
        (board[0][3] == board[1][2] == board[2][1] == board[3][0] == player)
    )

def is_board_full(board):
    """
    Return True if all elements of the board are non-zero.
    """
    return all(all(row) for row in board)

def main():
    board = [
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
        [0, 0, 0, 0],
    ]
    print_board(board)
    for player in cycle([1, 2]):
        make_move(board, player)
        print_board(board)
        if is_winner(board, player):
            print("Player {0} has won".format(player))
            break
        if is_board_full(board):
            print("Board is full")
            break

if __name__ == '__main__':
    main()