getattr() on nested functions?

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Thu Aug 21 17:14:12 CEST 2008


Gabriel Rossetti a écrit :
> Bruno Desthuilliers wrote:
>> Gabriel Rossetti a écrit :
>>> Terry Reedy wrote:
>> (snip)
>>>> 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))
>>>
>>> That's how I had done it originally (before the use of eval()), but 
>>> in this case also, since the functions are still nested, 
>>
>> Uh ??? You probably want to re-read the above code snippet.
>>
> Uh...yes, I didn't see the external/parent function was no longer there. 
> I prefer to nest mine though because I have several parent functions for 
> different tasks, so each child/nested function has a diff. 
> implementation, I find that cleaner than having n*4+n top-level 
> functions (+ n dicts), e.g. I prefer this :
> 
>    def __task1(self, action, *args):
>        def request(params):
>            pass
>        def submit(params, values):
>            pass
>        def update(params, values):
>            pass
>        def delete(params):
>            pass
>        return resultToXml(locals()[action](*args))
> 
>    def __task2(self, action, *args):
>        def request(params):
>            pass
>        def submit(params, values):
>            pass
>        def update(params, values):
>            pass
>        def delete(params):
>            pass
>        return resultToXml(locals()[action](*args))
> 
> 
> over this :
> 
(snip)
> 
> 
> I could use your callable approach, but like you said it may not be 
> worth the trouble.

The "trouble" I was talking about was not with using callable objects, 
but with trying to hack func.func_code to extract nested functions (if 
ever possible).

But anyway... The point of using callable objects is to avoid going thru 
the whole "setup" part again and again and again. Now if all your task 
functions only differ by the dispatch dict, there's at least another 
ways to avoid this runtime repetition - as well as coding repetition 
FWIW (warning : untested code):

def _make_task(func):
     dispatch = func()
     def _task(action, *args):
         return resultToXml(dispatch[action](*args))
     _task.__name__ = _task.func_name = func.__name__
    return _task

@_make_task
def _task1():
     def request(params):
         pass
     def submit(params, values):
         pass
     def update(params, values):
         pass
     def delete(params):
         pass
     return locals()


HTH



More information about the Python-list mailing list