3.3 Attributes#

Attribute usually means some specific quality. In python attribute is different than property.

class Insan:
    pass


x = Insan()
y = Insan()

We have created two objects/instances of class Insan namely x and y. We can bind attributes to class instances as follows:

x.name = "Ali"
x.dob = "1601"
y.name = "Hasan"
y.dob = "1624"

We can now check that the attributes have been associated with x and y.

print(x.name)
Ali
print(y.dob)
1624

It should be noticed that we have associated name and dob attributes to instances of Insan class i.e., x and y and not with Insan class. This is a dynamic way of attribute creation. Usually attributes are built inside the class, which we will cover later. what attributes does the instance x has? We can find it out as following

print(x.__dict__)
{'name': 'Ali', 'dob': '1601'}
print(y.__dict__)
{'name': 'Hasan', 'dob': '1624'}

We can also bind attributes to class names as well.

class Insan(object):
    pass


x = Insan()

Insan.cast = "Jat"

attribute cast is currently associated with instance x.

print(x.cast)
Jat

change the attribute cast associated with instance x

x.cast = "cheema"
print(x.cast)
cheema

what is attribute cast associated with class name ‘Insan’?

print(Insan.cast)  # >> Jat
Jat
y = Insan()
print(y.cast)  # what is attribute `cast` associated with instance `y`?
Jat

y was never assigned an attributed named cast. Still it threw a value, why?

Let’s make the attribute cast associated with Insan as Insaniyat now

Insan.cast = "insaniyat"
print('y_cast: ', y.cast)
print('x_cast: ', x.cast)
y_cast:  insaniyat
x_cast:  cheema
print(x.__dict__)
{'cast': 'cheema'}
print(y.__dict__)
{}

empty so if we call the attribute cast for instance y, python will first look into y attributes and if it does not find then it will look into attributes of Insan

# mappingproxy({'__module__': '__main__', '__weakref__': , '__doc__': None, '__dict__': , 'cast': 'insaniyat'})
print(Insan.__dict__)
{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Insan' objects>, '__weakref__': <attribute '__weakref__' of 'Insan' objects>, '__doc__': None, 'cast': 'insaniyat'}

So even though y instance itself does not have an attribute named cast so it checked whether the attribute cast exists in attributes of class Insan? If yes (which is the case) so y gets the attribute from Insan while x already had attribute named cast so it did not get attribute from class Insan.

If we try to get an attribute which is non-existing, we will get an AttributeError

# uncomment following line
# x.age  # >> AttributeError: `Insan` object has no attribute `age`

One way to prevent such error is to provide a default value for the attribute by

getattr(x, 'age', 90)
90

We can bind attributes to function names similarly

def chor(name):
    return name + ' chor hai'


chor.age = 61
print(chor.age)
61

We can use this trick to count number of function calls

def chor(name):
    chor.no_of_calls = getattr(chor, "no_of_calls", 0) + 1
    return name


for i in range(10):
    chor('nawaz')
10

To properly create class instances we need to define methods in the class body, which we will learn next

Total running time of the script: ( 0 minutes 0.006 seconds)

Gallery generated by Sphinx-Gallery