Generating getter methods with exec

Neal Norwitz neal at metaslash.com
Mon Mar 18 16:05:35 EST 2002


Stefan Schwarzer wrote:
> 
> I would like to generate some getter methods in a class which in fact
> access a stored dictionary. Unfortunately, I'm not able to get it work.
> 
> Suppose the following code is in getter_test.py:
> 
> class GetterTest:
>     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(self):\n"
>                      "    return self.%(dict_name)s['%(key)s']\n" %
>                      vars() )
>             print code
>             # this seems to be wrong but what should that be?
>             exec code in globals(), self.__dict__
> 
>     def key3(self):
>         return self._dict['key3']
> 
> In the interpreter (Python 2.2) I get:
> 
> >>> import getter_test
> >>> gt = getter_test.GetterTest()
> >>> gt._make_getters('_dict', ['key1', 'key2'])
> def key1(self):
>     return self._dict['key1']
> 
> def key2(self):
>     return self._dict['key2']
> >>> gt.key1()
> Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
> TypeError: key1() takes exactly 1 argument (0 given)
> 
> As can be seen, gt.key1() doesn't behave as expected (at least as
> expected by me ;-) ).
> 
> >>> gt.key1(gt)
> 'one'
> 
> This works, but needs an additional instance parameter which corresponds
> to this observation:
> 
> >>> gt.key1
> <function key1 at 0xa662c>
> 
> though I would rather like
> 
> >>> gt.key3
> <bound method GetterTest.key3 of <getter_test.GetterTest instance at 0xa648c>>
> 
> Can anyone tell me how I can generate the evaluated code as bound
> methods instead of functions? Many thanks in advance for any help! :-)

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'

Neal



More information about the Python-list mailing list