eval [was Re: dict to boolean expression, how to?]

Duncan Booth duncan.booth at invalid.invalid
Tue Aug 5 07:57:55 EDT 2014


Steven D'Aprano <steve+comp.lang.python at pearwood.info> wrote:

> Consider the namedtuple implementation in the standard library.
> There's a lot of criticism of it, some of it justified. It uses exec
> extensively, which means the code is dominated by a giant string
> template. This defeats your editor's syntax colouring, makes
> refactoring harder, and makes how the namedtuple works rather less
> understandable. It seems to me that it's only generating the __new__
> method which genuinely needs to use exec, the rest of the namedtuple
> could and should use just an ordinary class object (although I concede
> that some of this is just a matter of personal taste).
> 
> Raymond Hettinger's original, using exec for the entire inner class:
> 
> http://code.activestate.com/recipes/500261-named-tuples/
> 
> 
> My refactoring, with the bare minimum use of exec necessary:
> 
> https://code.activestate.com/recipes/578918-yet-another-namedtuple/


This may be a silly question, but what would stop you moving the exec inside the class?

So:
    ns = {'_new': tuple.__new__}

    class Inner(tuple):
        # Work around for annoyance: type __doc__ is read-only :-(
        __doc__ = ("%(typename)s(%(argtxt)s)"
                   % {'typename': typename, 'argtxt': argtxt})

        __slots__ = ()
        _fields = field_names

        exec """def __new__(_cls, %(argtxt)s):
        return _new(_cls, (%(argtxt)s))""" % { 'argtxt': argtxt } in ns, locals()

... and so on ...

and remove lines from 'ns = ...' to 'Inner.__new__ = ...'

The tests at the end of the file still pass so I'm not sure whether there is any situation
that wouldn't work.

For that matter I don't understand why tuple.__new__ needs to be pre-bound. Just referring 
to tuple.__new__ directly in the exec simplifies things even more as there is no need to 
specify any namespaces.

        exec """def __new__(_cls, %(argtxt)s):
        return tuple.__new__(_cls, (%(argtxt)s))""" % { 'argtxt': argtxt }

also passes the tests.

-- 
Duncan Booth 



More information about the Python-list mailing list