What is the relationship between __getattr__ and getattr?

Question:

I know this code is right:

class A:   
    def __init__(self):
        self.a = 'a'  
    def method(self):   
        print "method print"  

a = A()   
print getattr(a, 'a', 'default')   
print getattr(a, 'b', 'default')  
print getattr(a, 'method', 'default') 
getattr(a, 'method', 'default')()   

And this is wrong:

# will __getattr__ affect the getattr?

class a(object):
    def __getattr__(self,name):
        return 'xxx'

print getattr(a)

This is also wrong:

a={'aa':'aaaa'}
print getattr(a,'aa')

Where should we use __getattr__ and getattr?

Asked By: zjm1126

||

Answers:

getattr is a built-in function taking (at least) two arguments: the object from which you’re getting the attribute, and the string name of the attribute.

If the string name is a constant, say 'foo', getattr(obj, 'foo') is exactly the same thing as obj.foo.

So, the main use case for the built-in function getattr is when you don’t have the attribute name as a constant, but rather as a variable. A second important use case is when you pass it three arguments, rather than just two: in that case, if the attribute is absent from the object, getattr returns the third, “default”, argument, rather than raising an exception.

__getattr__ is a special method, defined in a class, that gets invoked when some attribute of an instance of that class is requested, and other normal ways to supply that attribute (via the instance’s __dict__, slots, properties, and so on) all failed. You can define it, for example, when you want to delegate otherwise-undefined attribute lookups to other objects.

So your second example is wrong because the builtin getattr can never be called with a single argument.

The third one fails because the dictionary you’re trying to “get an attribute” from does not have that attribute — it has items, which are totally disjoint from attributes of course.

Answered By: Alex Martelli

Alex’s answer was good, but providing you with a sample code since you asked for it 🙂

class foo:
    def __init__(self):
        self.a = "a"
    def __getattr__(self, attribute):
        return "You asked for %s, but I'm giving you default" % attribute


>>> bar = foo()
>>> bar.a
'a'
>>> bar.b
"You asked for b, but I'm giving you default"
>>> getattr(bar, "a")
'a'
>>> getattr(bar, "b")
"You asked for b, but I'm giving you default"

So in short answer is

You use

__getattr__ to define how to handle attributes that are not found

and

getattr to get the attributes

Answered By: Kimvais

__getattr__() is a special method function that you can define. When a member lookup fails, this function will be called.

getattr() is a function you can call to attempt a member lookup. If the lookup succeeds, you get the member (perhaps a method function object, or perhaps a data attribute object). getattr() can also return a default in the case the lookup fails.

If you declare a __getattr__() member function, you can make it succeed sometimes, or you can make it succeed every time.

class A(object):
    def __getattr__(self, name):
        return "I pretend I have an attribute called '%s'" % name

a = A()

print a.foo # prints "I pretend I have an attribute called 'foo'"

Python also has __getattribute__() which is always called on every lookup. It is very dangerous because it can make it impossible to access members normally.

class A(object):
    def __init__(self, value):
        self.v = value
    def __getattribute__(self, name):
        return "I pretend I have an attribute called '%s'" % name

a = A(42)

print a.v # prints "I pretend I have an attribute called 'v'"
print a.__dict__["v"] # prints "I pretend I have an attribute called '__dict__'"

Oops, it is now impossible to access a.v!

Answered By: steveha
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.