Override __getattr__ in Python
Do not miss this exclusive book on Binary Tree Problems. Get it now for free.
Magic methods or Dunder methods in Python are the methods having two underscores around the method's name. "Dunder" isn't some fictional city in Scranton, but it means “Double Under (Underscores)”. These are commonly used for operator overloading. Few examples for magic methods are: __init__
, __add__
, __len__
, __repr__
etc.
There are many methods like these but emphasizing particularly on __getattr__
, is called when an atrribute is not found in the usual place(i.e. it is not an instance attribute nor is it found in the class tree for self). In other words:
This method will allow you to intercept the references to attributes that don’t exist in your object. This method acts like an interrrupt function, i.e. when an exception occurs, the interrupt function associated with the exception is being called, in this case AttributeError is called for an inavlid attribute reference.
Now you know when this method is invoked in the code.
Syntax:
object. __getattr__(self, name)
self
Required. Instance of the class, passed automatically on call.
name
Required. The name of the attribute.
Pseudocode:
>>> class Foo(object):
def __getattr__(self, name):
if some_predicate(name):
# ...
else:
# Default behaviour
raise AttributeError
Imagine the Python interpreter has an object. A line of code requests the foo attribute. Is it there? Internally, you can think of Python objects as dictionaries. So the code checks if foo is in the dict. If so, return the value. If not, raise AttributeError.
When you implement "getattr", you get to decide how the exception is handled.
Declaring Class and its content making "a" as the attribute of class "Foo"
>>> class Foo:
a = "I am a class attribute!"
Invoking the class Foo:
>>> f = Foo() #assigning Foo class to f variable
>>> f.a
Note: Syntax for calling method: class.method(instance, args...)
Class Foo has "a" attribute when we called f.a. So, the outcome is:
>>> 'I am a class attribute!'
Now, what if the function does not have attribute that we are calling? Let's take another example.
>>> class Dummy(object):
pass
>>> d = Dummy()
>>> d.does_not_exist # Fails with AttributeError
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
d.does_not_exist
AttributeError: 'Dummy' object has no attribute 'does_not_exist'
This code raises an Attribute error. This is where getattr will be so useful.
Overriding getattr: If you want to do something fancy rather than your idle showing you some error, let's define getattr in the class and make it return some value. We are using this magic method to intercept the AttributeError and overloading it with our custom made defination.
Note that magic method is called when the inexistent attribute is looked up in the class.
>>> class Dummy(object):
def __getattr__(self, attr):
return attr.upper() #.upper capitalizes the letters in attr
>>> d = Dummy()
>>> d.this_does_not_exist
THIS_DOES_NOT_EXIST
Explanation
"d.this_does_not_exist" attempts to access the "this_does_not_exist" attribute of the class Dummy and therefore our custom defined method getattr is called returning the capitalized version of method name.
Note that getattr has two arguments,
"self" represents instance of the class and attr is the attribute name, in this case "this-does_not_exist"
Congratulations! Now we have succefully overriden getattr from its default AttributeError to something more meaningful.
The basic concept of getattr is to intercept the nonexistent attribute.
In our next example we are going to introduce method: init(self,name)
It is known as a constructor in object oriented concepts. This method is called when an object is created from the class and it allows the class to initialize the attributes of a class.
>>> class Frob:
... def __init__(self, man):
... self.bird = man
... def __getattr__(self, name):
... return 'No '{}' attribute.'.format(str(name))
>>> d = Frob("bird")
>>> d.man
Question
What will be the outcome of the above code?
>>> class D(object):
def __init__(self):
self.test=20
self.test2=21
def __getattr__(self,name):
if name=='test3':
return D().test3
else:
return "Attribute '{}' doesnt exist".format(str(name))
>>> D().test3
Question.
What will be the outcome of the above code?
Another similar method is getattribute when you want custom behaviour for the dot operator when accessing an attribute of an instance.
Read about various Magic Methods. Besides, you will need to read about __getattribute__
for answering next question
>>> class D(object):
def __init__(self):
self.test=20
self.test2=21
def __getattr__(self,name):
return "test3 is not an attribute"
def __getattribute__(self,name):
if name=='test3':
return 0.
else:
return object.__getattribute__(self, name)
>>> f = D()
>>> f.test3
Question
What will be the outcome of the above code?
With this article at OpenGenus, you must have the complete idea of overriding __getattr__
in Python. Enjoy.
Sign up for FREE 3 months of Amazon Music. YOU MUST NOT MISS.