#!/usr/bin/env python3
from functools import wraps
from typing import get_type_hints
from collections import defaultdict


_funcs_table = defaultdict(dict)


def overload(func):
    arg_type = tuple(get_type_hints(func).values())[0]
    _funcs_table[func.__name__][arg_type] = func
    @wraps(func)
    def wrapper(arg):
        return _funcs_table[func.__name__][type(arg)](arg)
    return wrapper

    
@overload
def f(x: int):
    print(f'f(int): {x}')


@overload
def f(x: str):
    print(f'f(str): {x}!')
    

@overload
def f2(y: int):
    print(f'f2(int): {y}')


@overload
def f2(y: float):
    print(f'f2(float): {y}')


def main():
    f(42)
    f('Hello')
    f2(43)
    f2(43.0003)
    
 
if __name__ == '__main__':
    main()