It's because you didn't properly copy the function. If you take a look at the signature of types.FunctionType
you'll see that it accepts 5 arguments:
class function(object)
| function(code, globals, name=None, argdefs=None, closure=None)
|
| Create a function object.
|
| code
| a code object
| globals
| the globals dictionary
| name
| a string that overrides the name from the code object
| argdefs
| a tuple that specifies the default argument values
| closure
| a tuple that supplies the bindings for free variables
You didn't pass any argdefs
, so the function has no optional arguments any more. The correct way to copy the function is
types.FunctionType(f.__code__,
{},
f.__name__,
f.__defaults__,
f.__closure__
)
However, this leads to another problem: Cutting off access to globals also cuts off access to builtins. If you try to use print
or open
or dict
or something similar in myFunction
, you'll get a NameError
. So the really correct way to write your decorator is this:
import builtins
import types
def noglobal(f):
return types.FunctionType(f.__code__,
{'__builtins__': builtins},
f.__name__,
f.__defaults__,
f.__closure__
)