Q:

Por que essa função fatorial não funciona?

def fatorial(n):
    fat = 1
    if n == 0 or n ==1:
        return 1
    else:
        for i in range(1,n+1):
            fat=i*fat
        return fat

def main():
    n =  int(input("Digite um numero que quer ver o fatorial: "))
    print(str(n) + "! = ", fatorial(n))

    # Executanto a função main():
    main()

não retorna nada

A:

Não retorna nada porque você chamou a função main dentro dela mesma; mas como a função nunca é chamada de fora, ela não será executada. Aparentemente foi erro na indentação do código apenas, então basta recuar em um nível a chamada de main:
def fatorial(n):
    fat = 1
    if n == 0 or n ==1:
        return 1
    else:
        for i in range(1,n+1):
            fat=i*fat
        return fat

def main():
    n =  int(input("Digite um numero que quer ver o fatorial: "))
    print(str(n) + "! = ", fatorial(n))

# Executanto a função main():
main()
# ^----- Aqui, main voltou um nível de indentação

Se você chamar range(1, n+1) para n = 0, não será executado o laço de repetição, pois o intervalo fica [1, 1[ e o valor que você definiu para fat ficaria 1, que é o resultado; semelhante acontece para quando n = 1, pois o intervalo será [1, 2[, executando para i = 1, ficando fat = 1 * fat, que ainda será 1, que também é o resultado. Ou seja, você não precisa dessa condição se n vale 0 ou 1:
def fatorial(n):
    fat = 1
    for i in range(1, n+1):
        fat=i*fat
    return fat

E fazer fat = i * fat é o mesmo que fat *= i, então pode simplificar isso também:
def fatorial(n):
    fat = 1
    for i in range(1, n+1):
        fat *= i
    return fat

