Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python class attributes and their initialization

I'm quite new in python and during these days I'm exploring classes. I have a question concerning attributes and variables inside classes: What is the difference between defining an attribute via just q=1 in the body of the class and via defining self.q=1 inside the __init__? For example, what is the difference between the following two possibilities?

class MyClass1:
    q=1
    def __init__(self,p):
        self.p=p
    def AddSomething(self,x):
        self.q = self.q+x

and

class MyClass2:
    def __init__(self,p):
        self.q=1
        self.p=p
    def AddSomething(self,x):
        self.q = self.q+x

The output of for example:

>>> my=MyClass1(2)
>>> my.p
2
>>> my.q
1
>>> my.AddSomething(7)
>>> my.q
8

does not depend on whether MyClass1 or MyClass2 is used. Neither in MyClass1 nor in MyClass2 does an error occur.

like image 622
Chris Avatar asked May 15 '15 11:05

Chris


People also ask

What are the attributes of a class in Python?

Class attributes belong to the class itself they will be shared by all the instances. Such attributes are defined in the class body parts usually at the top, for legibility. Unlike class attributes, instance attributes are not shared by objects.

What is class initialization in Python?

__init__ method "__init__" is a reseved method in python classes. It is called as a constructor in object oriented terminology. This method is called when an object is created from a class and it allows the class to initialize the attributes of the class.

How are the class attribute initialized explain?

A instance attribute is assigned directly to an instance of a class, usually in __init__ by assigning to self (such as with self. p = p ), but you can assign attributes to an instance at any time.


2 Answers

Classes as well as their instances in python uses dictionary like data structure to store the information.

So for each class definition, a dictionary will be allocated where the class level information (class variables) will be stored. And for each instance of that particular class, a separate dictionary(self) will be allocated where the instance specific information(instance variables) will be stored.

So now the next question is: How the lookup for a particular name will be performed ??

And answer to this question is that if you are accessing the names through some instance, the instance specific dictionary will be searched first and if the name is not found there, then the class dictionary will be searched for that name. So if the same value is defined at both levels that former one will be overridden.

Note that when you write d['key'] = val where d is a dictionary, 'key' will automatically be added to the dictionary if not already present. Otherwise the current value will be overwritten. Keep this in mind before reading the further explanation.

Now lets go through the code you have used to describe your problem:

MyClass1

class MyClass1:
    q=1
    def __init__(self,p):
        self.p=p
    def AddSomething(self,x):
        self.q = self.q+x

1. my = Myclass1(2) #create new instance and add variables to it.

    MyClass = {"q" : 1}
    my = {"p" : 2}

2. my.p    # =2, p will be taken from Dictionary of my-instance.

3. my.q    # =1, q will be takn from MyClass dict. (Not present in dictionary of my-instance).

4. my.AddSomething(7) # This method access the value of q (using self.q) first 
                      # which is not defined in my dict and hence will be taken
                      # from dictionary of MyClass. After the addition operation,
                      # the sum is being stored in self.q. Note that now we are
                      # adding the name q to Dictionary of my-instance and hence                   
                      # a new memory space will be created in Dictionary of my-instance
                      # and the future references to self.q will fetch the value
                      # of self.q from dictionary of my-instance.

    MyClass = {"q" : 1}
    my = {"p" : 2, "q" : 8}

5. my.q   # =8, q now is available in dictionary of my-instance.
like image 96
Shasha99 Avatar answered Oct 23 '22 00:10

Shasha99


q=1 inside the class is a class attribute, associated with the class as a whole and not any particular instance of the class. It is most clearly accessed using the class itself: MyClass1.q.

A instance attribute is assigned directly to an instance of a class, usually in __init__ by assigning to self (such as with self.p = p), but you can assign attributes to an instance at any time.

Class attributes can be read either using the class binding (MyClass.q) or an instance binding (my.q, assuming it is not shadowed by an instance attribute with the same name). They can only be set, however, using a class binding. Setting a value with an instance binding always modifies an instance attribute, creating it if necessary. Consider this example:

>>> a = MyClass1()
>>> a.q
1
>>> a.q = 3    # Create an instance attribute that shadows the class attribute
3
>>> MyClass1.q
1
>>> b = MyClass1()
>>> b.q   # b doesn't have an instance attribute q, so access the class's
1
like image 44
chepner Avatar answered Oct 23 '22 00:10

chepner