I come from Ruby and I'm getting used to the "explicit over implicit" philosophy that Python follows, but I was confused earlier about how I actually make class methods. Now, I want verification that I am indeed correct in the following:
Every method in a class is essentially a class method in Python.
For example:
class Employee(object):
employeeCount = 0
def __init__(self, name):
self.name = name
employeeCount += 1
def get_name(self):
return self.name
def get_employee_count():
return employeeCount
If I understand this correct, for instance david = Employee("david") the following two are equivalent:
david.get_name() and Employee.get_name(david). Likewise, it makes sense that we could say get_employee_count is a class method too, but it doesn't rely on any instance, hence why we don't pass in an instance. This is why it doesn't make sense to type david.get_employee_count(), because this would be Employee.get_employee_count(david), but get_employee_count doesn't take in a parameter, namely the instance. This concludes that we would just type Employee.get_employee_count().
Am I correct in my thinking? Thank you.
2 Answers 2
No, you're not quite right. For something to be a class method rather than an instance method, you have to use the classmethod decorator. And that method still takes a parameter, but that param is the class, not the instance. So:
@classmethod
def get_employee_count(cls):
return cls.employeeCount
Classes don't actually define a block scope inside them in Python, so just referring to employeeCount in the method wouldn't work - that's why the cls param is used.
For clarification, a decorator is simply a wrapper around a function - it could also be written
def _get_employee_count(cls):
return cls.employeeCount
get_employee_count = classmethod(_get_employee_count)
and classmethod is a built-in function.
Also note, in Python (as I thought in Ruby too) we wouldn't normally write accessors for simple variables like name, we'd just access them directly.
10 Comments
get_employee_count()?employeeCount = 0 would generate an error.david.employeeCount += 1 you'll actually create an instance attribute that shadows the class one, and the changes won't reflect in the class variable. In __init__, you'll need to explicitly access the class: self.__class__.employeeCount += 1 should work.type(self).employeeCount instead of self.__class__.employeeCountTrue. Functions that deal with objects' instances should have self in its parameters. Otherwise, they are considered class methods.
EDIT
Class methods doesn't mean static methods! They're not static methods unless you add the decorator @staticmethod before the definition of the class function
3 Comments
@classmethod decorator to make class methods.
get_employee_count()is a not a class method, it's a normal function inside a class.(or static method in py2.x, if used with @staticmethod)e = Employee("David"); print e.get_employee_count()won't work becauseget_employee_countdoesn't know whereemployeeCountisselfparameter, so that'll raise an exception.Employee.get_employee_count().