eval
and exec
are for dynamically executing simple Python expressions or more complex statements (respectively).
So, one practical example from the standard library, collections.namedtuple
uses exec
to dynamically define a __new__
method for the tuple subclass being returned:
# Create all the named tuple methods to be added to the class namespace
s = f'def __new__(_cls, {arg_list}): return _tuple_new(_cls, ({arg_list}))'
namespace = {'_tuple_new': tuple_new, '__name__': f'namedtuple_{typename}'}
# Note: exec() has the side-effect of interning the field names
exec(s, namespace)
__new__ = namespace['__new__']
__new__.__doc__ = f'Create new instance of {typename}({arg_list})'
if defaults is not None:
__new__.__defaults__ = defaults
This sometimes makes sense, however, this is often abused by inexperience programmers to write unnecessarily dynamic code, e.g. dynamically creating a bunch of variables, when they should have used a list
or a dict
(or some other container) instead.