There are three types of methods in Python classes.
--Normal method (instance method)
--The first argument is mandatory and is customarily set to self
.
--When called via an instance, the called instance is included in the first argument.
--When called via a class, the arguments at the time of calling are passed as they are.
--Class method
--Define with @classmethod
. The first argument is mandatory and is customarily set to cls
.
--When called via an instance, the class of the called instance is included in the first argument.
--When called via a class, that class is included in the first argument.
--Static method
--Define with @staticmethod
. The argument is not required.
--The argument when called is passed as it is.
class C:
val = 20
def __init__(self):
self.val = 1
def normal_method(self, v):
return self.val + v + 2
@classmethod
def class_method(cls, v):
return cls.val + v + 3
@staticmethod
def static_method(v):
return C.val + v + 4
i = C()
i.normal_method(5) # i.val + 5 + 2 = 1 + 5 + 2 = 8
i.class_method(6) # C.val + 6 + 3 = 20 + 6 + 3 = 29
i.static_method(7) # C.val + 7 + 4 = 20 + 7 + 4 = 31
C.normal_method(5) # requires 2 args but 1: error
C.normal_method(i, 6) # i.val + 6 + 2 = 1 + 6 + 2 = 9
C.normal_method(C, 7) # C.val + 7 + 2 = 20 + 7 + 2 = 29
C.class_method(8) # C.val + 8 + 3 = 20 + 8 + 3 = 31
C.static_method(9) # C.val + 9 + 4 = 20 + 9 + 4 = 33
Normal methods are still functions.
--The first argument is self
, which is just a promise, and there are no restrictions on the type of self
.
--When you call it via an instance, the processing system automatically puts that instance in the first argument.
Taking this as a counter-product, the behavior can be changed by the first argument.
class C:
#Added to the above
def trick_method(arg, v):
if isinstance(arg, C):
return arg.val * 2 * v
else:
return C.val + arg * v
i.trick_method(4) # i.val * 2 * 4 = 1 * 2 * 4 = 8
C.trick_method(5) # requires 2 args but 1: error
C.trick_method(6, 7) # C.val + 6 * 7 = 20 + 6 * 7 = 62
C.trick_method(i, 8) # i.val * 2 * 8 = 1 * 2 * 8 = 16
C.trick_method(C, 9) # C.val + C * v: error
The above trick_method ()
behaves like a normal method via an instance and like a static method via a class.
Normally, if the behavior is different, it should be a different method.
I came up with such a strange usage while creating a class that manages instances as a group.
class Student:
rooms = {}
def __init__(self, room):
self.myroom = room
if not room in Student.rooms:
Student.rooms [room] = []
Student.rooms [room].append(self)
def classmates(self_or_room):
if isinstance(self_or_room, Student):
self = self_or_room
for s in Student.rooms[self.myroom]:
if s != self:
yield s
elif self_or_room in Student.rooms:
room = self_or_room
return iter(Student.rooms[room])
Ann = Student('3-A')
Bob = Student('3-B')
Cathy = Student('3-B')
Dan = Student('3-A')
Ellen = Student('3-A')
Fred = Student('3-B')
mates_of_ann = Ann.classmates() # Dan, Ellen
mates_of_3A = Student.classmates('3-A') # Ann, Dan, Ellen
mates_of_bob = Bob.classmates() # Cathy, Fred
mates_of_3B = Student.classmates('3-B') # Bob, Cathy, Fred
This method cannot be used with methods with decorators (such as @ property
or @ classmethod
).
Recommended Posts