How to customize getattr(obj, prop) function ?

P

Pierre

Hi,

Sorry in advance, english is not my main language :/

I'd like to customize the result obtained by getattr on an object : if
the object has the requested property then return it BUT if the object
doesn't has actually this property return something else.

In my case, I can't use getattr(object, property, default_value).

I tried to write a class with a __getattr__ method and even a
__getattribute__ method but this doesn't do what I want....

Maybe I didn't correctly understand this :
http://docs.python.org/ref/attribute-access.html

Here is a piece of my code :
=====================================
class myclass:
"""docstring"""

a = 'aa'
b = 'bb'

def __getattr___(self, ppt):
"""getattr"""
if hasattr(self, ppt):
return self.ppt
else:
return "my custom computed result"

def __getattribute__(self, ppt):
"""getattribute"""
if hasattr(self, ppt):
return self.ppt
else:
return "my custom computed result"

if __name__ == "__main__":

d = myclass()
p1 = getattr(d, "a")
print p1
p2 = getattr(d, "b")
print p2
p3 = getattr(d, "c")
print p3
================================

I get an AttributeError when accessing to the property named "c".

Any explanation/solution to my problem ?
 
R

Richard Copeland

Try this:

class Class:
a='aa'
b='bb'
def __getattr__(self, ppt):
return 'custom computed result'

__getattr__ is only called when "normal" attribute lookup fails, so
there's no need for the "hasattr" test.

Also, I believe that __getattribute__ only applies to new-style classes
(classes derived from "object"), and it will override *all* attribute
accesses, anyway (meaning you'd have infinite recursion if you used it
since you look up "self.ppt")
 
R

Richard Copeland

Try this:

class Class:
a='aa'
b='bb'
def __getattr__(self, ppt):
return 'custom computed result'

__getattr__ is only called when "normal" attribute lookup fails, so
there's no need for the "hasattr" test.

Also, I believe that __getattribute__ only applies to new-style classes
(classes derived from "object"), and it will override *all* attribute
accesses, anyway (meaning you'd have infinite recursion if you used it
since you look up "self.ppt")
 
R

Richard Copeland

Try this:

class Class:
a='aa'
b='bb'
def __getattr__(self, ppt):
return 'custom computed result'

__getattr__ is only called when "normal" attribute lookup fails, so
there's no need for the "hasattr" test.

Also, I believe that __getattribute__ only applies to new-style classes
(classes derived from "object"), and it will override *all* attribute
accesses, anyway (meaning you'd have infinite recursion if you used it
since you look up "self.ppt")
 
G

George Sakkis

Pierre said:
Hi,

Sorry in advance, english is not my main language :/

I'd like to customize the result obtained by getattr on an object : if
the object has the requested property then return it BUT if the object
doesn't has actually this property return something else.

In my case, I can't use getattr(object, property, default_value).

I tried to write a class with a __getattr__ method and even a
__getattribute__ method but this doesn't do what I want....

Maybe I didn't correctly understand this :
http://docs.python.org/ref/attribute-access.html

Here is a piece of my code :
=====================================
class myclass:
"""docstring"""

a = 'aa'
b = 'bb'

def __getattr___(self, ppt):
"""getattr"""
if hasattr(self, ppt):
return self.ppt
else:
return "my custom computed result"

1) You have misspelled the method by adding a hard-to-spot third
trailing underscore.
2) __getattr__ is called when normal lookup fails, so the condition
evaluates always to False.
def __getattribute__(self, ppt):
"""getattribute"""
if hasattr(self, ppt):
return self.ppt
else:
return "my custom computed result"

1) __getattribute__ is called for new-style classes only (those that
inherit directly or indirectly from object).
2) Even if your class was new-style, this would enter an infinite loop
because 'self.ppt' calls __getattribute__ again.

George
 
R

Richard Copeland

I tested the exact code I sent you on python 2.4.1. What version of
Python are you using?

Thanks,
Rick
 
R

Richard Copeland

I tested the exact code I sent you on python 2.4.1. What version of
Python are you using?

Thanks,
Rick
 
R

Richard Copeland

I tested the exact code I sent you on python 2.4.1. What version of
Python are you using?

Thanks,
Rick
 
P

Pierre

I'm using python 2.4.3.

I removed the method __getattribute__

The mistake was my 3rd underscore :S sorry for wasting your time...

The problem is solved ! Thx all !

PS: Richard youre message are displayed 3 times ?!
 
B

bruno at modulix

Pierre said:
Hi,

Sorry in advance, english is not my main language :/

I'd like to customize the result obtained by getattr on an object : if
the object has the requested property then return it BUT if the object
doesn't has actually this property return something else.

So implement __getattr__(self, name).
In my case, I can't use getattr(object, property, default_value).

Why so ?
I tried to write a class with a __getattr__ method and even a
__getattribute__ method but this doesn't do what I want....

Warning: __getattribute__ will take over normal attribute lookup. It can
be really tricky. Anyway, you don't need it for your use case - just
stick with __getattr__() and you'll be ok.
Maybe I didn't correctly understand this :
http://docs.python.org/ref/attribute-access.html

Here is a piece of my code :
=====================================
class myclass:

Make this :
class MyClass(object):

"""docstring"""

a = 'aa'
b = 'bb'

a and b are class attributes, not instance attributes. If you want
per-instance attributes (which is the most usual case...), you need to
define them in a method - usually the __init__() method:

def __init__(self):
self.a = 'aa'
self.b = 'bb'
def __getattr___(self, ppt):
"""getattr"""
if hasattr(self, ppt):
return self.ppt

__getattr__() will be called only if the normal attribute lookup fails.
So calling hasattr(self, ...) in __getattr__ is useless. More than
this: the fact that __getattr__() has benn called means that normal
lookup has already failed, so hasattr() will end up calling
__getattr__()...
else:
return "my custom computed result"




(snip)


if __name__ == "__main__":

d = myclass()
p1 = getattr(d, "a")

You do understand that getattr(d, "a") is the same as d.a, don't you ?
print p1
p2 = getattr(d, "b")
print p2
p3 = getattr(d, "c")
print p3
================================

I get an AttributeError when accessing to the property named "c".

Any explanation/solution to my problem ?

1/ use new-style classes
2/ only implement __getattr__()


here's a minimal working example:

class MyClass(object):
def __init__(self, default='default'):
self.a = 'aa'
self.b = 'bb'
self._default = default

def __getattr__(self, name):
return self._default

m = MyClass()
m.a
m.b
m.toto

HTH
 
P

Pierre

I don't want to use getattr(object, property, default_value) because
I'm using external code and I don't want to modify or patch it. In this
code, the call is getattr(object, property).

On my objects, I must provide default values depending on the property
that was requested, the default value is not always the same.

And Yes I understand that obj.a is equivalent to getattr(obj, 'a') BUT
the difference between class attribute and instance attribute... :S
 
B

bruno at modulix

Pierre said:
I don't want to use getattr(object, property, default_value) because
I'm using external code and I don't want to modify or patch it. In this
code, the call is getattr(object, property).

Seems like a perfectly valid reason !-)
On my objects, I must provide default values depending on the property
that was requested, the default value is not always the same.

On what does it depends ? Attribute name ? Class ? Phase of the moon ?
And Yes I understand that obj.a is equivalent to getattr(obj, 'a') BUT
the difference between class attribute and instance attribute... :S

If you mean you don't understand the difference between a class
attribute and an instance attribute, then it would be time to learn
Python's OO 101 - else you're in for trouble.

For short, an instance attribute has a per-instance value and is
(usually) stored in the object's __dict__, while a class attribute is
shared by all instances of the class and is (usually) stored in the
class's __dict__.


class Parrot(object):
cls_attr = 'class attribute'

def __init__(self):
self.instance_attr = 'instance attribute'

import pprint
pprint.pprint(Parrot.__dict__.items())
p = Parrot()
pprint.pprint(p.__dict__.items())

print Parrot.cls_attr
try:
print Parrot.instance_attr
except AttributeError, e:
print e
# will lookup 'cls_attr' in p, then in Parrot
print p.cls_attr
print p.instance_attr

# will create an instance attribute 'cls_attr' in
# object p, shadowing Parrot.cls_attr
p.cls_attr = 'WTF ?'
print p.cls_attr
print Parrot.cls_attr

del p.cls_attr
print p.cls_attr
print Parrot.cls_attr

HTH
 
B

Ben Finney

[Please provide some context in your reply, so we know what questions
or comments you're replying to.]

Pierre said:
I don't want to use getattr(object, property, default_value) because
I'm using external code and I don't want to modify or patch it.

You can subclass the class you want to modify, and override its behaviour.

class ScaryExternalThing(object):
""" The external class we don't want to modify. """

class OurModifiedFriendlyThing(ScaryExternalThing):
""" Class for use by our code. """

attr_defaults = {
'foo': "eggs",
'bar': "beans",
}

def __getattr__(self, name):
""" Method invoked when getting an unknown attribute """

value = attr_defaults.get(name, "spam")
return value
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top