getattr() on nested functions?

Terry Reedy tjreedy at udel.edu
Wed Aug 20 13:37:55 EDT 2008



Gabriel Rossetti wrote:
> Bruno Desthuilliers wrote:
>> Gabriel Rossetti a écrit :

>>> 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.

What Bruno meant here, I believe, is that there is probably a hackish 
way to get the nested functions, but it indeed would not be worth the pain.

 >>  The fact that functions are objects doesn't make nested
>> functions methods of that object.

A def statement is ultimately an assignment statement.  The name of the 
nested function is a local variable just like any other local name.

 >> 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()
>>
> Yes, very hackish :-)

No, not at all hackish, but one standard way to do what you want.

>> 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)
>>
>>
> Ok, thanks, that works :-), like I told Gabriel G., I keep on forgetting 
> locals() exists :-)

Unlike the class approach, this requires recreating the constant 
functions and dict with each call to _test.  Quick to write but a bit 
'dirty', in my opinion.  Another standard idiom is to set up the 
constants outside the function:

def request(params):
     pass
def submit(params, values):
     pass
def update(params, values):
     pass
def delete(params):
     pass
dispatch = {'request':request, 'submit':submit, 'update':update, 
'delete':delete}

def _test(self, action, *args):
     return resultToXmo(dispatch[action](*args))

Terry Jan Reedy





More information about the Python-list mailing list