473,573 Members | 2,778 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

getattr() on nested functions?

Hello,

I can't get getattr() to return nested functions, 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. 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(res ult)

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)")

but I didn't find that very clean.

Thank you,
Gabriel
Aug 20 '08 #1
9 3976
Gabriel Rossetti <ga************ **@arimaz.comwr ites:
I can't get getattr() to return nested functions, 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.
Note that the nested function is created anew each time you call
toto(), so there's no reason for it to be stored anywhere. What is
stored is the internal compiled code object used to create the inner
function, but it's not easy to get to it, nor is it all that useful to
try. If you really need this, you can explicitly store the inner
function in the outer one's dict:

def outer():
if not hasattr(outer, 'inner'):
def inner():
pass
outer.inner = inner
f = outer.inner # same as getattr(outer, 'inner')
print f # same as print str(f)
>>outer()
<function inner at 0xb7cfc294>
>>outer.inner
<function inner at 0xb7cfc294>
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(res ult)

where "action" is a string containing either "request", "submit",
"update", or "delete".
Use locals()[action](*args).
Aug 20 '08 #2
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(get attr(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(res ult)

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(res ult)
HTH
Aug 20 '08 #3
Bruno Desthuilliers wrote:
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.
Ok
>
>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(get attr(self, action)(*args))

_test = _Test()
Yes, very hackish :-)
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(res ult)

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(res ult)

Ok, thanks, that works :-), like I told Gabriel G., I keep on forgetting
locals() exists :-)
HTH
--
http://mail.python.org/mailman/listinfo/python-list
Aug 20 '08 #4


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(get attr(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(res ult)

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':requ est, 'submit':submit , 'update':update ,
'delete':delete }

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

Terry Jan Reedy
Aug 20 '08 #5
Terry Reedy wrote:
>

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.
Yes, I understood that :-)
>
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.
Ok
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(get attr(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(res ult)

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':requ est, 'submit':submit , 'update':update ,
'delete':delete }

def _test(self, action, *args):
return resultToXmo(dis patch[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, they are
re-created and so is the dict, so I don' t see a gain from the locals()
method.
>
Terry Jan Reedy
--
http://mail.python.org/mailman/listinfo/python-list
Aug 21 '08 #6
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':requ est, 'submit':submit , 'update':update ,
'delete':delet e}

def _test(self, action, *args):
return resultToXmo(dis patch[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.

Aug 21 '08 #7
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':requ est, 'submit':submit , 'update':update ,
'delete':dele te}

def _test(self, action, *args):
return resultToXmo(dis patch[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(loc als()[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(loc als()[action](*args))
over this :

def task1_request(p arams):
pass
def task1_submit(pa rams, values):
pass
def task1_update(pa rams, values):
pass
def task1_delete(pa rams):
pass

def task2_request(p arams):
pass
def task2_submit(pa rams, values):
pass
def task2_update(pa rams, values):
pass
def task2_delete(pa rams):
pass

dispatch_task1 = {'request':task 1_request, 'submit':task1_ submit,
'update':task1_ update, 'delete':task1_ delete}
dispatch_task2 = {'request':task 2_request, 'submit':task2_ submit,
'update':task2_ update, 'delete':task2_ delete}

def _task1(self, action, *args):
return resultToXml(dis patch_task1[action](*args))

def _task2(self, action, *args):
return resultToXml(dis patch_task2[action](*args))
I could use your callable approach, but like you said it may not be
worth the trouble.

Gabriel

Aug 21 '08 #8
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':requ est, 'submit':submit , 'update':update ,
'delete':del ete}

def _test(self, action, *args):
return resultToXmo(dis patch[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(loc als()[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(loc als()[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(dis patch[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
Aug 21 '08 #9
On Aug 21, 10:14*am, Bruno Desthuilliers <bruno.
42.desthuilli.. .@websiteburo.i nvalidwrote:
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':requ est, 'submit':submit , 'update':update ,
'delete':dele te}
>>def _test(self, action, *args):
* * return resultToXmo(dis patch[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(loc als()[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(loc als()[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(dis patch[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(res ult)

def request(self,pa rams):
pass

def submit(self,par ams, values):
pass

def update(self,par ams, values):
pass

def delete(self,par ams):
pass

Keep us posted which one works for you.

Aug 21 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
2609
by: Brian Roberts | last post by:
I'm confused about the use of hasattr/getattr, or possibly namespaces. I know how to do this: class UnderstandThis(object): def do_foo(self): pass def do_bar(self): pass def doit(self, cmd): funcname = 'do_' + cmd if hasattr(self, funcname): getattr(self, funcname)()
6
2560
by: Andy Baker | last post by:
Hi there, I'm learning Python at the moment and trying to grok the thinking behind it's scoping and nesting rules. I was googling for nested functions and found this Guido quote: (http://www.python.org/search/hypermail/python-1993/0343.html) "This is because nested function definitions don't have access to the local variables of the...
7
2242
by: block111 | last post by:
Hello, code like this: int f1(int x){ int f2(int y){ return y*y; } if(x > 0) return f2(x);
4
2298
by: Wolfgang Draxinger | last post by:
If you know languages like Python or D you know, that nested functions can be really handy. Though some compilers (looking at GCC) provide the extension of nested functions, I wonder, how one could implement an equivalent behaviour with plain C (in this case I'm thinking of the language I'm developing, which shall be converted into C for...
3
1955
by: Rotlaus | last post by:
Hello, lets assume i have some classes: class A(object): def __init__(self): b = B() class B(object): def __init__(self):
2
1654
by: Johannes Bauer | last post by:
Nick Keighley schrieb: Why is there actually a *need* for nested functions? If functionality of subfunctions which are only locally visible is desired, why not put the nesting function parent and its nested children all in one module, declare the children static - voila. Std-C. Regards, Johannes
8
7945
by: Gregor Horvath | last post by:
Hi, class A(object): test = "test" class B(object): a = A() In : B.a.test
0
1186
by: Gabriel Genellina | last post by:
En Wed, 20 Aug 2008 05:34:38 -0300, Gabriel Rossetti <gabriel.rossetti@arimaz.comescribi�: Yes, functions are objects, but inner functions aren't attributes of the outer; they live in its local namespace instead (and inner functions won't exist until the outer function executes) Try using locals()
4
10469
by: maestro | last post by:
Why are these functions there? Is it somehow more idiomatic to use than to do obj.field ? Is there something you can with them that you can't by obj.field reference?
0
7784
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7705
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
8033
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8206
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7796
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
8077
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6426
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5601
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
3739
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.