Add-in for input() with validation What do you think about this code? Do you have some advices and remarks for me about them? I have started learning python recently.

types = {
    "str": str,
    "int": int,
    "float": float,
    "complex": complex
}


def my_input(kind, msg, msg_wrong, detail):
    """ Add-in for input(). Performs validation of the data entered.
    :param kind: data type. The keys of the dictionary types. 
                 If an error occurs, a str is expected.
    :param msg: a welcome message, such as "Enter a number -&gt; "
    :param msg_wrong: own message in case of error
    :param detail: detailed error description (True or False)
    :return: entered value with type kind
    """
    method = types.get(kind, str)
    while True:
        try:
            value = method(input(msg))
            break
        except ValueError as e:
            print(msg_wrong, detail * str(e))
    return value


msg = "-&gt; "
msg_wrong = "Error"

print(my_input("int", msg, msg_wrong, False))
print(my_input("hello", msg, msg_wrong, True))  # wrong type, will str
print(my_input("complex", msg, msg_wrong, True))

"""
-&gt; hi
Error 
-&gt; 15
15
-&gt; some text
some text
-&gt; some text 2
Error complex() arg is a malformed string
-&gt; 4-j
(4-1j)
"""
Your function looks usable, useful and follows PEP8, well done.
Coupling types and kind together seems like a poor descision. Since functions are firstclass in Python you can just pass the function.

This would change your functions to something like:


my_input(int, msg, msg_wrong, False)



This would have the drawback that if you don't pass a valid function, then it will blow-up. But has the added benifit of allowing more types with less code.


import datetime
my_input(datetime.fromisoformat, msg, msg_wrong, False)



You can also fix the drawback by changing kind to an argument with a default value.


def my_input(msg, msg_wrong, detail, kind=str)
my_input(msg, msg_wrong, True)


It's not immediatly clear why you would want to log only certain errors with the detail argument.

If I were to show or silence errors I would use the logging module.
I'll leave configuring the logger to you, but usage would be:

import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

...

def my_input(kind, msg, msg_wrong):
    method = types.get(kind, str)
    while True:
        try:
            value = method(input(msg))
            break
        except ValueError as e:
            logger.debug(e)
            print(msg_wrong)
    return value

...

print(my_input("int", msg, msg_wrong))
logger.setLevel(logging.DEBUG)
print(my_input("hello", msg, msg_wrong))
print(my_input("complex", msg, msg_wrong))


It's not apparent to me why you'd like to log some but not other errors. If being able to change the level of different calls to my_input is of the upmost importance then it'd make more sense to me for you to pass the logging level.


def my_input(kind, msg, msg_wrong, level=logging.DEBUG):
    ...
            logger.log(level, e)


I'm not used to seeing assignment, break and then a return out of a while true loop. When I do this I only use return.


import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)


def my_input(msg, msg_wrong, cast=str):
    while True:
        try:
            return cast(input(msg))
        except ValueError as e:
            logger.debug(e)
            print(msg_wrong)


msg = "-&gt; "
msg_wrong = "Error"

print(my_input(msg, msg_wrong, int))
print(my_input(msg, msg_wrong))
print(my_input(msg, msg_wrong, complex))