Beginning Python guessing game
Without changing the global structure of your code, here are a few things that could make it better.

NB: I will try to cover as much as I can, skipping objects and if-reduction, as it has already been covered in another answer

Docstrings

You use regular comments at the beginning of your functions. Their purpose is to indicate what the function does, therefore they should be docstrings. The difference is that it is stored in the __doc__ special variable.

def get_number(level):
    """selects a random number in range depending on difficulty selected"""
    if level == "e":
        # rest of the function


About get_number

You could use a dictionary of levels to make it shorter and easier to understand. Also more flexible when you want to change levels later, or add new levels.

levels = {'e': 20, 'm': 100, 'h': 1000}


The content of the function is then something like:

if level != "e" and level != "m" and level != "h":
    print ("Invalid input!")
    get_number()
else:
    number = random.randint(1, levels[level])
return number


Or even better, try and catch a KeyError that is raised when the key does not exist. Final get_number function:

levels = {'e': 20, 'm': 100, 'h': 1000}

def get_number(level):
    """selects a random number in range depending on difficulty selected"""
    try:
        number = random.randint(1, levels[level])
    except KeyError:
        print ("Invalid input!")
        get_number()
    return number


About guess_number

Golden rule : never rely on a user input (you can read about it here for example). As we've seen before, the user does not always enter what you asked for, and this can cause your game to crash. Fortunately, using try/except can solve this problem. I've kept the use of the levels dictionary here.

def guess_number(level):
    """function that prompts the user to guess within range
    depending on chosen difficulty"""
    try:
        guess = int(input("Guess a number between 1 and "+str(levels[level])+":\n"))
    except KeyError:
        print('This should never have happened. "level" is not part of the levels')
    except (ValueError, NameError, SyntaxError):
        print('Invalid input\n')
        guess = guess_number(level)
    return guess


Naming arguments

Sometimes functions can be obscure, it can be helpful for others (and future you) to name arguments, as Python allows nicely.

if level == "e":
    com_guesses = round(random.normalvariate(mu=3.7, sigma=1.1))


This makes it way easier to understand.

Magic numbers

Speaking of the line of code just above, 3.7 and 1.1 seem to come out of nowhere. Two solutions to get this straight:


Create constants (not my favorite)


For instance,

EASY_MU = 3.7
EASY_SIGMA = 1.1
MEDIUM_MU = 5.8
# ...


and the line becomes much more understandable

if level == "e":
    com_guesses = round(random.normalvariate(mu=EASY_MU, sigma=EASY_SIGMA))



Use dictionaries (again)


We could improve the levels dictionary to make it contain what we want for later.

levels = {'e': {'size': 20, 'mu': 3.7, 'sigma': 1.1},
          'm': {'size': 100, 'mu': 5.8, 'sigma': 1.319},
          'h': {'size': 1000, 'mu': 8.99, 'sigma': 1.37474}
          }


Then the whole method becomes way more readable

def com_num_guesses(level):
    """function to get the number of guesses taken by the computer"""
    try:
        com_guesses = round(random.normalvariate(mu=levels[level]['mu'], sigma=levels[level]['sigma']))
    except KeyError:
        print('This should never have happened. "level" is not part of the levels')
    print("The computer guessed the number in {0} guesses! Can you beat that?".format(com_guesses))
    return com_guesses


Also note that in get_number and guess_number, we will now have calls to levels[level]['size'] since the dictionary has changed.

Lauching

It is recommended to encapsulate your mainloop function within an if __name__ == '__main__' condition. That way, it will not get run if this module is imported by someone else. More information on that here.

if __name__ == '__main__':
    mainloop()


Global remarks

You used a lot of recursive calls. This is OK, since the number of calls remains small (once per user mistake). But I personally have a preference for while True loops that break as soon as the user input is correct. It uses less memory.

This answer is already quite long, and I've given you pieces of information to improve your code, not revolutionized the whole structure, that's why I didn't copy the whole code at the end.