0

I am trying to learn oop concepts and i chose python. As far as I know self.count and employee.count both calls the class variable count and they both should have same value. However, for the following code, I see that self.count is 1 and employee.count is 0.

class employee:
    count=0
    def __init__(self,x):
        self.x=x
        self.count=self.count+1
        print ("this method is executed")
        print (self.count)
        print (employee.count)
emp1=employee("John")       
Moses Koledoye
  • 77,341
  • 8
  • 133
  • 139
vijay
  • 87
  • 2
  • 8
  • So they clearly are *not* the same variable; what, then, is your question? Did you try making other `employee` objects? – Scott Hunter Dec 28 '16 at 20:59
  • No... self.count and employee.count both refers to the same class variable count which I declared earlier – vijay Dec 28 '16 at 21:01
  • @vijay But only until you declare the instance variable `self.count`... – Keiwan Dec 28 '16 at 21:06

3 Answers3

2

This is somewhat subtle because of the line below:

self.count = self.count + 1

Here, the self.count on the left hand side and the self.count on the right hand side are not the same thing!

This line of code creates an instance variable on the self object (an employee instance) with a name (i.e. count) which shadows the variable of the same name that already exists on the class object (i.e. the employee class).

The right hand side is evaluated first, and that actually resolves the name self.count on the class object. The presence of an instance attribute is actually checked for beforehand, but it doesn't exist yet since the instance attribute has not been bound. Then, after the right hand side has been evaluated (i.e. the name self.count gets resolved, and 1 is added to it), the result of evaluation is bound to an instance attribute.

Both variables co-exist:

>>> emp1.count
1
>>> emp1.__class__.count
0

The key thing to learn here is Python's attribute lookup process: the instance namespace is checked and then the class namespace is checked.

wim
  • 338,267
  • 99
  • 616
  • 750
  • So, in the right hand side (self.count+1) , initially self.count is looked up and no instance variable is found. So, It took the value of class variable count (which is initialized earlier). After it found the value (0) it incremented the value and assigned it to instance variable . Please correct me if I am wrong – vijay Dec 28 '16 at 21:29
  • That's correct. – wim Dec 28 '16 at 21:38
0

emp1 is an instance of the class employee. Each instance has its own set of variables, called instance variables. These are the ones assigned as self.var = ... inside methods of the class.

If you try accessing emp1.var and this instance variable is not assigned, Python looks for a var variable attached to the class of emp1, meaning it looks up employee.var. These kind of variable are called a class variable, and they are defined the way you have defined count=0 at the top of your class.

Now, in your example, self.count=self.count+1, the left-hand side assigns to the instance, so you are creating an instance variable called count. The right-hand side, however, looks up self.count, which does not yet exist as an instance variable, so employee.count is really used instead. This confusing behavior is avoided if you do not use the same variable name for both an instance variable and a class variable.

jmd_dk
  • 12,125
  • 9
  • 63
  • 94
-1

If You want to count number of created Employee, You have to create method which will invoke to every objects at all (not individually).

To do that, create method and decorate her with @staticmethod. Notice that this method don't have self in parenthesies. Moreover create variable (here: count), which also invoke to every class object at all (without self. before).

Finally put our count variable inside __init__ method with += 1 equation (than every time when new Employee will be created __init__ will add +1 to our variable). But remember to add Employee. before count here, to count every single create Employee as a class population.

class Employee(object):
    count = 0

    @staticmethod
    def status():
        print(Employee.count)

    def __init__(self, x):
        self.x = x
        Employee.count += 1
        print("this method is executed")
        print("Now, we have got", Employee.count, "Employees")


emp1 = Employee("John")

We can show up population number with :

print(emp1.count)
emp1.status()
print(Employee.count)