Generating getter methods with exec

Neal Norwitz neal at metaslash.com
Mon Mar 18 18:36:51 EST 2002


Stefan Schwarzer wrote:
> 
> Hello Neal
> 
> thank you for your answer. :)
> 
> Neal Norwitz wrote:
> > You don't need to generate code.  This should do what you want:
> >
> > class GetterTest:
> >     def __init__(self):
> >         self._dict = {'key1': 'one',
> >                       'key2': 'two',
> >                       'key3': 'three'}
> >
> >     def __getattr__(self, attr):
> >         try:
> >             return self._dict[attr]
> >         except KeyError:
> >             raise AttributeError, "getting attribute '%s'" % attr
> >
> > >>> g = GetterTest()
> > >>> g.key1
> > 'one'
> > >>> g.key2
> > 'two'
> > >>> g.key3
> > 'three'
> > >>> g.key4
> > Traceback (most recent call last):
> >   File "<stdin>", line 1, in ?
> >   File "<stdin>", line 8, in __getattr__
> > AttributeError: getting attribute 'key4'
> 
> Yes, that's the straightforward solution. :-)
>
> On the other hand, what I posted was a simplified example. Finally, I
> will have several dictionary-like objects and not all of their items
> should be accessible by get/set methods (only some of the corresponding
> attributes belong to the public interface). I'm a bit afraid the overhead
> of dynamically making all the decisions for every access might be slow
> (though it may well be that all will be fast enough).
> 
> So to rephrase the problem a bit: I would like to generate simple getters
> and setters with rather little decision overhead during the actual accesses.

:-) Well in that case:

class GetterTest1:
    def __init__(self):
        self._dict = {'key1': 'one',
                      'key2': 'two',
                      'key3': 'three'}

    def _make_getters(self, dict_name, key_list):
        for key in key_list:
            code = "def %(key)s(): return %(dict_name)s['%(key)s']\n" % vars()
            exec code in self.__dict__, self.__dict__

-----------------

The problem is the distinction between bound vs unbound methods.
BTW, this version is about 3 times faster than the previous.  It
took .03 seconds to call key1 10,000 times vs. .1 seconds.

Neal



More information about the Python-list mailing list