getattr() on nested functions?

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Wed Aug 20 05:31:59 EDT 2008


Gabriel Rossetti a écrit :
> Hello,
> 
> I can't get getattr() to return nested functions,

Of course. Nested functions are not attributes of their container function.

> I tried this :
> 
>  >>> def toto():
> ...     def titi():
> ...             pass
> ...     f = getattr(toto, "titi")
> ...     print str(f)
> ...
>  >>> toto()
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
>  File "<stdin>", line 4, in toto
> AttributeError: 'function' object has no attribute 'titi'
>  >>>
> 
> I thought that since functions are objects, that I could obtain it's 
> nested functions.

Well, there's probably a very hackish way, but it's not worth the pain. 
The fact that functions are objects doesn't make nested functions 
methods of that object. If what you really want are methods, then you 
can write your own callable:

class _Test(object):
   def request(self, params):
       pass
   def submit(self, params, values):
       pass
   def update(self, params, values):
       pass
   def delete(self, params):
       pass
   def __call__(self, action, *args):
       return resultToXml(getattr(self, action)(*args))

_test = _Test()

But read the remaining before...

> How come it doesn't work and what can I do to 
> fix/replace it? I'm using it in code that is like this :
> 
> def __test(self, action, *args):
>        def request(params):
>            pass
>                  def submit(params, values):
>            pass
>                  def update(params, values):
>            pass
>                  def delete(params):
>            pass
>              result = getattr(__test, action)(*args)
>              return resultToXml(result)
> 
> where "action" is a string containing either "request", "submit", 
> "update", or "delete". I was using an evel() with this form :
> 
> result = eval(action + "(params, values)")

Wrong use case for eval, as usual.

> but I didn't find that very clean.

indeed !-)

locals() is your friend.

def _test(self, action, *args):
        def request(params):
            pass
        def submit(params, values):
            pass
        def update(params, values):
            pass
        def delete(params):
            pass
        result = locals()[action](*args)
        return resultToXml(result)


HTH



More information about the Python-list mailing list