Python Forum
How to access class variable? instances vs class
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to access class variable? instances vs class
#1
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 
Reply
#2
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.
Reply
#3
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
Reply
#4
drSlump Wrote:it works in both ways though

Can you post the whole code? It should not give the same pay.
Reply
#5
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?
Reply
#6
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.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Python inner classes inheritance from parent class Abedin 8 702 Apr-23-2025, 05:56 AM
Last Post: Gribouillis
  Accessing method attributes of python class Abedin 6 905 Apr-14-2025, 07:02 AM
Last Post: buran
  Python class members based on a type value voidtrance 7 1,282 Apr-11-2025, 10:10 PM
Last Post: deanhystad
  Create a new subclass in a Python extension based on an existing class voidtrance 6 1,444 Mar-25-2025, 06:37 PM
Last Post: voidtrance
  printing/out put issue with class arabuamir 3 1,007 Aug-25-2024, 09:29 AM
Last Post: arabuamir
  Class test : good way to split methods into several files paul18fr 5 3,827 Jul-17-2024, 11:12 AM
Last Post: felixandrea
  sharepoint: Access has been blocked by Conditional Access policies CAD79 0 2,230 Jul-12-2024, 09:36 AM
Last Post: CAD79
  [split] Class and methods ebn852_pan 15 3,387 May-23-2024, 11:57 PM
Last Post: ebn852_pan
  [SOLVED] [listbox] Feed it with dict passed to class? Winfried 3 1,328 May-13-2024, 05:57 AM
Last Post: Larz60+
  Class and methods Saida2024 2 1,135 May-13-2024, 04:04 AM
Last Post: deanhystad

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020