Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use a static variable inside a class in Python

class Cls:
    counter = 0
    def __init__(self, name):
        self.name = name
        self.counter += 1
    def count(self):
        return self.counter

I'm learning python, what I want to have is a static counter that counts the number of times the class has been instantiated, but every time I create an instance counter gets recreated and count() function always returns 1. I want something that in java would look like this

public class Cls {
    private static int counter = 0;
    private String name;
    public Cls(String name) {
        this.name = name;
        counter ++;
    }
    public static int count(){
        return counter;
    }
}
like image 219
MrSir Avatar asked Jan 03 '23 13:01

MrSir


1 Answers

There are two ways to access a class attribute: you can either access it directly on a class, or you can read it through self (but not rebind it). Accessing a class attribute through self won't work if there is already a value set directly on the instance so you would normally try to use the class to access a class attribute.

class Cls:
    counter = 0
    def __init__(self, name):
        self.name = name
        Cls.counter += 1
    def count(self):
        return Cls.counter

When you write self.counter += 1 this is a shorthand for self.counter = self.counter + 1 and as with any other binding through self it sets an instance attribute.

This can be useful if you want a default value for instance attributes, you can set them as class attributes and then just update them in the instances which want different values, but to avoid confusion you probably want to avoid using self at all when accessing class attributes.

You can also consider making the count method into a class method and moving the increment into another method:

@classmethod
def increment(cls):
    cls.counter += 1

@classmethod
def count(cls):
    return cls.counter

if you do that then each subclass will have its own independent counter. That may or may not be what you want here. The cls parameter here is the class that was actually instantiated, this can be useful if you can a whole class hierarchy, or even just a base class CountsInstances where you can put this code once and reuse it with multiple independent counters.

Decorating each function with @staticmethod will give you something close to the Java code:

class Cls:
    counter = 0
    def __init__(self, name):
        self.name = name
        self.increment()

    @staticmethod
    def increment():
        Cls.counter += 1

    @staticmethod
    def count():
        return Cls.counter
like image 62
Duncan Avatar answered Jan 05 '23 14:01

Duncan