Simple converter: Is it better to use a function within a function?
I think it depends on how self-evident the code is. If it's clear from context what the intent of a calculation or function call is, then I agree with @Sam that the code will be more concise without giving it a name.

On the other end though, depending on the context, 9 * x / 5 + 32 might not be obvious in what it's doing. You may find that giving that equation a name helps readability in general, which may trump conciseness.

In this exact case though, I don't think there's a ton of benefit to giving it a name unless you strongly suspected that you'd need it elsewhere in the future, or you personally like the way having a name reads. I think that that formula is well-known enough that most people would be able to tell what it's doing; especially when it's inside of a function called temperature.



In this case though, there's no good reason that the function should be inside of temperature. Defining one function inside of another suggests that the inner function has no meaning outside of enclosing function, which may be the case if you're forming a closure over a local variable or something similar. In this case though, cel_to_far is just simply taking a parameter and returning an output. It isn't using anything local to temperature. If you wanted to have a standalone function, I would definitely move cel_to_far outside of temperature. If you want it to be "private" to the module, prefix the name with an _:

def _cel_to_far(x):
    return 9 * x / 5 + 32

def temperature():
    . . .




You're only using two spaces of indentation. Please use four-spaces, as per PEP8.



t = user_in isn't useful. You're taking a line to rename an already short variable name to something obscure. If you need to reduce line lengths, there are other more readable ways of achieving that. Here though, the longest line is only 76 characters long after fixing the indentation and getting rid of t. That's not very long, and user_in is a much more descriptive name.



In both your main functions, you're getting float input from the user manually with a while True and try. In an effort to reduce duplication and centralize how you're handling input, I'd make a helper function:

def _ask_for_float():
    while True:
        try:
            return float(input('Number to convert:&gt; '))

        except ValueError:
            print('Enter numbers only!')


Instead of repeating the while True: try . . . part, make that a function, then call the function. Notice how much neater this makes each of the functions:

def _ask_for_float():
    while True:
        try:
            return float(input('Number to convert:&gt; '))

        except ValueError:
            print('Enter numbers only!')


def _cel_to_far(x):
    return 9 * x / 5 + 32


def temperature():
    user_in = _ask_for_float()
    result = 'is: {} degrees Fahrenheit'.format(_cel_to_far(user_in))

    print('Input: {} degrees Celcius'.format(user_in), result)


def milli():
    user_in = _ask_for_float()
    n = 1 * user_in / 25.4

    print('Input: {} millimeters is: {} inches'.format(user_in, n))


That immediately fixes any line-length issues by removing two levels of indentation, and makes each function trivial.



Finally, lines like:

print('Input: {} degrees Celcius'.format(user_in), result)


Can be written inline using f-strings. I'd collapse result back into the literal for readability as well:

def temperature():
    user_in = _ask_for_float()

    print(f'Input: {user_in} degrees Celcius is: {_cel_to_far(user_in)} degrees Fahrenheit')