Function objects are created by function definitions. The only
operation on a function object is to call it:
func(argument-list).
There are really two flavors of function objects: built-in functions
and user-defined functions. Both support the same operation (to call
the function), but the implementation is different, hence the
different object types.
The implementation adds two special read-only attributes:
f.func_code is a function's code
object(see below) and f.func_globals is
the dictionary used as the function's global namespace (this is the
same as m.__dict__ where m is the module in which
the function f was defined).
Function objects also support getting and setting arbitrary
attributes, which can be used to, e.g. attach metadata to functions.
Regular attribute dot-notation is used to get and set such
attributes. Note that the current implementation only supports
function attributes on functions written in Python. Function
attributes on built-ins may be supported in the future.
Functions have another special attribute f.__dict__
(a.k.a. f.func_dict) which contains the namespace used to
support function attributes. __dict__ can be accessed
directly, set to a dictionary object, or None. It can also be
deleted (but the following two lines are equivalent):