Il existe trois types de méthodes dans les classes Python.
@ classmethod
. Le premier argument est obligatoire et est généralement défini sur cls
.@ staticmethod
. L'argument n'est pas obligatoire.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
Les méthodes normales sont toujours des fonctions.
En prenant cela comme un contre-produit, le comportement peut être modifié par le premier argument.
class C:
#Ajouté à ce qui précède
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
Le trick_method ()
ci-dessus se comporte comme une méthode normale via une instance et comme une méthode statique via une classe.
Normalement, si le comportement est différent, il devrait s'agir d'une méthode différente.
J'ai trouvé une utilisation si étrange lors de la création d'une classe qui gère les instances en tant que groupe.
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
Cette méthode ne peut pas être utilisée avec des méthodes avec des décorateurs (comme «@ property» ou «@ classmethod»).
Recommended Posts