Python Forum
How to access class variable? instances vs class - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: How to access class variable? instances vs class (/thread-23085.html)



How to access class variable? instances vs class - drSlump - Dec-10-2019

Hello everyone, I am learning OOP in python, specifically class variables. It is clear to me what they are, but I do not get why they should be accessed through the instance. Referring to the following tutorial in the method apply_raise the variable can be accessed through the instance (line 15 --> self.pay = int( self.pay * self.raise_amount )). I tried to access the variable through the class (line 16 --> self.pay = int( self.pay * Employee.raise_amount ), and it works in the same way, at least it looks so to me. Is there any difference?

class Employee:

    raise_amount = 1.04

    def __init__(self ,first ,last ,pay ):
        self.first = first
        self.last = last
        self.pay = pay
        self.email = first+"."+last+"@company.com"

    def fullname(self):
        return "{} {}".format(self.first, self.last)

    def apply_raise(self):
        self.pay = int( self.pay * self.raise_amount )
       #self.pay = int( self.pay * Employee.raise_amount )
        return self.pay 



RE: How to access class variable? instances vs class - Gribouillis - Dec-10-2019

At first sight, there is no difference: if it doesn't find the raise_amount member in the instance, Python will look for the member in the class, then in the ancester classes if any.

The self.raise_amount is the most robust syntax if you decide to change the structure of the classes later. For example if you change the name of the Employee class, you won't need to change self.raise_amount. Things get even better when you start defining subclasses, for example
class SpecialEmployee(Employee):
    raise_amount = 1.10

jane = SpecialEmployee('Jane', 'Doe', 5000)
jane.apply_raise()
Then Jane's new pay will be 5500 because self.raise_amount will use Jane's class instead of the Employee class.


RE: How to access class variable? instances vs class - drSlump - Dec-11-2019

Thanks for the answer, I got the point about changing the class' name. I tested your subclass and it works in both ways though (self.raise_amount and Employee.raise_amount)...am I doing something wrong? Huh


RE: How to access class variable? instances vs class - Gribouillis - Dec-11-2019

drSlump Wrote:it works in both ways though

Can you post the whole code? It should not give the same pay.


RE: How to access class variable? instances vs class - drSlump - Dec-11-2019

Sorry it was my mistake. Everything works fine and I think I got the point. Here is the code:

class Employee:

    raise_amount = 2

    def __init__(self ,first ,last ,pay ):
        self.first = first
        self.last = last
        self.pay = pay
        self.email = first+"."+last+"@company.com"

    def fullname(self):
        return "{} {}".format(self.first, self.last)

    def apply_raise(self):
        # self.pay = int( self.pay * self.raise_amount )
        self.pay = int( self.pay * Employee.raise_amount)
        return self.pay

class SpecialEmployee(Employee):
    raise_amount = 10
So if I use self.raise_amount in the method apply_raise of the ancestor class Employee, the raise_amount class variable is always bound to the instance. Hence, if I change its value either in a child class (e.g. SpecialEmployee) or in any instance of the ancestor/child class, this value will be used. If I use Employee.raise_amount the class variable can be changed only through the class, thus Employee.raise_amount == value and will stay that value. I think I can say in a way that, using self.raise_amount the class variable is always accessible by the current instance of the class, right?

What confused me is that even defining Employee.raise_amount == value, I can still do:

emp_1 = Employee("John", "Doe", 5000)
emp_1.raise_amount = 1.1
print('raise_amount emp_1= ',emp_1.raise_amount)
print(emp_1.apply_raise())
print(emp_1.__dict__)
that provides as output:
Output:
raise_amount emp_1= 1.1 10000 {'first': 'John', 'last': 'Doe', 'pay': 10000, 'email': '[email protected]', 'raise_amount': 1.1}
so it seemed to me that the variable class raise_amount was changed, but it was not, actually the method apply_raise provides the correct result. But why is the 'raise_amount': 1.1 listed in emp_1.__dict__ then?


RE: How to access class variable? instances vs class - Gribouillis - Dec-11-2019

You cannot change the class attribute through the assignment
emp_1.raise_amount = 1.1
This creates (or updates) an instance attribute without changing the class attribute. This is because instance attributes don't need to be declared in python. Assigning emp_1.spam = value creates the spam instance attribute, regardless of what the class contains.