It is possible using a code-generation + exec pattern. It is also possible by instantiating a types.FunctionType instance directly. But a much simpler solution would be to leave the generic name, and then inject an alias (another reference to the same function object) for the dynamic name into whichever namespace you want.
>>> def generic_function(x):
... print(x ** 2)
...
>>> dynamic_name = "func_abc"
>>> globals()[dynamic_name] = generic_function
>>> func_abc(3)
9
To inject in some other module namespace that would be a setattr call:
setattr(other_mod, dynamic_name, generic_function)
You could also rewrite the function's __name__ attribute if you wanted to, but there's probably not much point.
funcs = {'abc': fun1}Then you could call the function corresponding to 'abc' asfuncs['abc']().