469,609 Members | 2,231 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,609 developers. It's quick & easy.

getattr nested attributes

Hi,

class A(object):
test = "test"

class B(object):
a = A()
In [36]: B.a.test
Out[36]: 'test'

In [37]: getattr(B, "a.test")
---------------------------------------------------------------------------
<type 'exceptions.AttributeError' Traceback (most recent call last)

/<ipython consolein <module>()

<type 'exceptions.AttributeError'>: type object 'B' has no attribute
'a.test'

???

Documentation says B.a.test and getattr(B, "a.test") should be equivalent.

http://docs.python.org/lib/built-in-funcs.html

any help?

Greg
Aug 15 '08 #1
8 5985
Gregor Horvath wrote:
any help?
I guess you missunderstood the sentence "For example, getattr(x,
'foobar') is equivalent to x.foobar.". getattr(x, "foo.bar") is not
equivalant to x.foo.bar.
Aug 15 '08 #2
Gregor Horvath wrote:
Hi,

class A(object):
test = "test"

class B(object):
a = A()
In [36]: B.a.test
Out[36]: 'test'

In [37]: getattr(B, "a.test")
---------------------------------------------------------------------------
<type 'exceptions.AttributeError' Traceback (most recent call
last)

/<ipython consolein <module>()

<type 'exceptions.AttributeError'>: type object 'B' has no attribute
'a.test'

???
I think that message is pretty clear. B doesn't have an attribute "a.test",
it has an attribute "a" which in turn has an attribute "test". You can
access it by calling getattr() twice,
>>getattr(getattr(B, "a"), "test")
'test'

make your own function that loops over the attributes, or spell it
>>reduce(getattr, "a.test".split("."), B)
'test'
Documentation says B.a.test and getattr(B, "a.test") should be equivalent.

http://docs.python.org/lib/built-in-funcs.html
No, it doesn't.

Peter
Aug 15 '08 #3
Peter Otten schrieb:
make your own function that loops over the attributes, or spell it
>>>reduce(getattr, "a.test".split("."), B)
'test'
Thank's, but this does not work for this case:

class A(object):
test = "test"

class B(object):
a = [A(),]

In [70]: reduce(getattr, "a[0].test".split("."), B)
---------------------------------------------------------------------------
<type 'exceptions.AttributeError' Traceback (most recent call last)

/<ipython consolein <module>()

<type 'exceptions.AttributeError'>: type object 'B' has no attribute 'a[0]'

Seems that I have to use eval ?
I have a mapping text file (data) which contains such attributes strings
and those attributes should be read.

--
Greg
Aug 15 '08 #4
Gregor Horvath wrote:
Peter Otten schrieb:
>make your own function that loops over the attributes, or spell it
>>>>reduce(getattr, "a.test".split("."), B)
'test'

Thank's, but this does not work for this case:

class A(object):
test = "test"

class B(object):
a = [A(),]

In [70]: reduce(getattr, "a[0].test".split("."), B)
---------------------------------------------------------------------------
<type 'exceptions.AttributeError' Traceback (most recent call
last)

/<ipython consolein <module>()

<type 'exceptions.AttributeError'>: type object 'B' has no attribute
'a[0]'
Like the screwdriver doesn't work with a nail?
Seems that I have to use eval ?
I have a mapping text file (data) which contains such attributes strings
and those attributes should be read.
When you pass data to eval() it becomes code. If you trust the source of
that text file that would be the easiest approach. Otherwise google
for 'safe eval'.

Peter
Aug 15 '08 #5
On Fri, 15 Aug 2008 11:12:04 +0200, Gregor Horvath wrote:
Thank's, but this does not work for this case:

class A(object):
test = "test"

class B(object):
a = [A(),]

In [70]: reduce(getattr, "a[0].test".split("."), B)
---------------------------------------------------------------------------
<type 'exceptions.AttributeError' Traceback (most recent call last)

/<ipython consolein <module>()

<type 'exceptions.AttributeError'>: type object 'B' has no attribute 'a[0]'

Seems that I have to use eval ?
Nope. Always ask getattr for small things and it will like you:
>>getattr(getattr(B, 'a')[0], 'test')
'test'
>>>
it works because:
>>getattr(B, 'a') == B.a
True
>>getattr(B, 'a')[0] == B.a[0]
True
>>>
--
Regards,
Wojtek Walczak,
http://www.stud.umk.pl/~wojtekwa/
Aug 15 '08 #6
On Fri, 15 Aug 2008 11:12:04 +0200, Gregor Horvath wrote:
Peter Otten schrieb:
>make your own function that loops over the attributes, or spell it
>>>>reduce(getattr, "a.test".split("."), B)
'test'

Thank's, but this does not work for this case:

class A(object):
test = "test"

class B(object):
a = [A(),]

In [70]: reduce(getattr, "a[0].test".split("."), B)

Seems that I have to use eval ?
No you don't.

I have a mapping text file (data) which contains such attributes strings
and those attributes should be read.
It might help if you showed what those strings were. I can guess two
likely formats, so here's a few possible solutions.
def grab1(obj, ref):
# Assume ref looks like "attr index"
attr, index = ref.split()
return getattr(obj, attr)[int(index)]
import re
x = re.compile(r'(.*)\[(.*)\]')
def grab2(obj, ref):
# Assume ref looks like "attr[index]"
mo = x.match(ref)
attr = mo.group(1)
index = int(mo.group(2))
return getattr(obj, attr)[index]

def grab3(obj, ref):
# Assume ref looks like "attr[index]"
return eval("obj." + ref)

Here they are in action:
>>grab1(B(), "a 0")
<__main__.A object at 0xb7c7948c>
>>grab2(B(), "a[0]")
<__main__.A object at 0xb7c7948c>
>>grab3(B(), "a[0]")
<__main__.A object at 0xb7c7948c>
Which is fastest?
>>from timeit import Timer
Timer("grab1(b, 'a 0')",
.... "from __main__ import B, grab1; b = B()").repeat()
[3.9213471412658691, 2.8718900680541992, 2.875662088394165]
>>Timer("grab2(b, 'a[0]')",
.... "from __main__ import B, grab2; b = B()").repeat()
[6.1671040058135986, 5.2739279270172119, 5.1346590518951416]
>>Timer("grab3(b, 'a[0]')",
.... "from __main__ import B, grab3; b = B()").repeat()
[33.484487056732178, 34.526612043380737, 34.803802013397217]
The first version is about twice as fast as the regular expression
version, which in turn is about six times as fast as the version using
eval.
--
Steven
Aug 15 '08 #7
On 15 Aug, 10:35, Gregor Horvath <g...@gregor-horvath.comwrote:
>
<type 'exceptions.AttributeError'>: type object 'B' has no attribute
'a.test'
You have to realise that attributes can have names beyond those
supported by the usual attribute access syntax. For example:

class C: pass

setattr(C, "x.y", 123)
getattr(C, "x.y") # gives 123
setattr(C, "class $$$", 456)
getattr(C, "class $$$") # gives 456

Note that there's no way of using the object.name syntax to access
these attributes, although some proposals have been made to allow it
in some fashion. What you should conclude from this is that the name
argument to setattr and getattr is just a name, not an expression,
even if you can construct names which look like expressions or other
syntactically meaningful fragments of code.
Documentation says B.a.test and getattr(B, "a.test") should be equivalent.

http://docs.python.org/lib/built-in-funcs.html
No, the documentation says that the name must be "the name of one of
the object's attributes", not an expression fragment that if combined
with the name of the object and evaluated would yield an attribute
from some object or other reachable via the original object.

Paul
Aug 15 '08 #8
Gregor Horvath wrote:
Thank's, but this does not work for this case:

class A(object):
test = "test"

class B(object):
a = [A(),]

In [70]: reduce(getattr, "a[0].test".split("."), B)
---------------------------------------------------------------------------
<type 'exceptions.AttributeError' Traceback (most recent call last)
getattr fetches a named attribute, it doesn't evaluate random code
snippets. please read the manual.

</F>

Aug 15 '08 #9

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

8 posts views Thread by Steven D'Aprano | last post: by
2 posts views Thread by Sledge | last post: by
3 posts views Thread by Rotlaus | last post: by
9 posts views Thread by Gabriel Rossetti | last post: by
reply views Thread by Gabriel Genellina | last post: by
4 posts views Thread by maestro | last post: by
reply views Thread by devrayhaan | last post: by
reply views Thread by gheharukoh7 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.