getattr() on nested functions?
castironpi
castironpi at gmail.com
Thu Aug 21 13:50:11 EDT 2008
On Aug 21, 10:14 am, Bruno Desthuilliers <bruno.
42.desthuilli... at websiteburo.invalid> wrote:
> 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
Here's more ideas:
Use a wrapper to give the function access to itself as an object:
@auto
def f( self, arg ):
assert self== f
In your original example:
@auto
def toto( toto ):
def titi():
pass
f = getattr(toto, "titi")
print str(f)
Should work, untested. Another is to use a wrapper to participate
functions in a dictionary:
@entry( 'a' )
def a( arg ):
a_stuff( )
@entry( 'b' )
def b( arg ):
b_stuff
You could even make 'entry' a class instance, so you can specialize
and vary it in other cases, untested.
Last one is just use a class, untested:
class __Test:
def __test(self, action, *args):
result = getattr(self, action)(*args)
return resultToXml(result)
def request(self,params):
pass
def submit(self,params, values):
pass
def update(self,params, values):
pass
def delete(self,params):
pass
Keep us posted which one works for you.
More information about the Python-list
mailing list