classmethod และ staticmethod ซึ่งเป็นฟังก์ชันมาตรฐานที่นิยมนำมาใช้เพื่อตกแต่งเมธอดภายในคลาสclassmethoddef จากนั้นก็ใช้ classmethod โดย
ชื่อเมธอด = classmethod(ชื่อเมธอด)
classmethod เป็นเดคอเรเตอร์ ดังนั้นโดยทั่วไปแล้วจะนิยมใช้ @ มากกว่า นั่นคือ
@classmethod
def ชื่อเมธอด(self,พารามิเตอร์ที่เหลือ):
self ก็จะแทนตัวคลาสเสมอ แม้ว่าเมธอดจะถูกเรียกใช้จากอินสแตนซ์ก็ตามclass Cla:
a = 'แอตทริบิวต์ a ของคลาส Cla'
@classmethod
def metamon(self):
return [self,self.a]
print(Cla.metamon()) # ได้ [<class '__main__.Cla'>, 'แอตทริบิวต์ a ของคลาส Cla']
metamon ขึ้นมาเป็นเมธอดของคลาส Cla ทำงานโดยคืนตัวคลาสและแอตทริบิวต์ a ออกมาc = Cla()
c.a = 'แอตทริบิวต์ a ของอินสแตนซ์ c'
print(Cla.a) # ได้ แอตทริบิวต์ a ของคลาส Cla
print(c.a) # ได้ แอตทริบิวต์ a ของอินสแตนซ์ c
print(c.metamon()) # ได้ [<class '__main__.Cla'>, 'แอตทริบิวต์ a ของคลาส Cla']
metamon ผลที่ได้ก็ยังคงออกมาเป็นตัวคลาสและแอตทริบิวต์ a ของคลาส แทนที่จะเป็นตัวอินสแตนซ์และแอตทริบิวต์ a ของอินสแตนซ์@classmethod ละก็ผลที่ได้ก็จะเป็นของตัวอินสแตนซ์เองแทนผู้กล้า ขึ้นมาเพื่อใช้เป็นตัวอย่างมาแล้ว คราวนี้เราจะลองสร้างคล้ายๆกันขึ้นมาแต่จะเพิ่มเมธอดของคลาสลงไป
class ผู้กล้า:
ทุกคน = []
def __init__(self,ชื่อ,เลเวล,hpสูงสุด):
self.ชื่อ = ชื่อ
self.เลเวล = เลเวล
self.hpสูงสุด = hpสูงสุด
self.hp = hpสูงสุด
self.__class__.ทุกคน += [self]
@classmethod
def ฟื้นhpทุกคน(self):
for แต่ละคน in self.ทุกคน:
แต่ละคน.hp = แต่ละคน.hpสูงสุด
ฟื้นhpทุกคน มีไว้ฟื้น hp ให้ทุกคนกลับมาเต็มหมดทุกคน เอาไว้ นี่เป็นแอตทริบิวต์ของคลาส ทำหน้าที่เก็บออบเจ็กต์ที่เป็นผู้กล้าทั้งหมด โดยจะเห็นว่าในเมธอด __init__ มี self.__class__.ทุกคน += [self] นั่นคือเมื่อมีการสร้างผู้กล้าคนใหม่ขึ้นจะถูกเก็บลงในลิสต์นี้ฟื้นhpทุกคน ก็จะดึงออบเจ็กต์จากลิสต์ ทุกคน เพื่อมาทำการฟื้นเลือดโดยแก้ค่า hp ให้เท่ากับค่า hpสูงสุดผู้เล่น1 = ผู้กล้า('นายก',10,20) # สร้างผู้เล่น
ผู้เล่น2 = ผู้กล้า('นายข',11,22)
ผู้เล่น1.hp -= 10 # โดนอัด
ผู้เล่น2.hp -= 18
print(ผู้กล้า.ทุกคน) # แสดงลิสต์ที่เก็บผู้เล่นทุกคน
print('hp ของผู้เล่น1: %d'%ผู้เล่น1.hp) # แสดง hp ที่ลดไปแล้ว
print('hp ของผู้เล่น2: %d'%ผู้เล่น2.hp)
ผู้กล้า.ฟื้นhpทุกคน() # ใช้เมธอดเพื่อฟื้นพลังทุกคน
print('==ฟื้นพลัง==')
print('hp ของผู้เล่น1: %d'%ผู้เล่น1.hp) # แสดง hp หลังฟื้นพลัง
print('hp ของผู้เล่น2: %d'%ผู้เล่น2.hp)
[<__main__.ผู้กล้า object at 0x1123f5940>, <__main__.ผู้กล้า object at 0x1123f54e0>]
hp ของผู้เล่น1: 10
hp ของผู้เล่น2: 4
==ฟื้นพลัง==
hp ของผู้เล่น1: 20
hp ของผู้เล่น2: 22
classmethod นั่นคือ staticmethodstaticmethod มีไว้สร้างสิ่งที่เรียกว่าเมธอดสถิต การใช้งาน staticmethod นั้นคล้ายกับ classmethod คือเป็นเดคอเรเตอร์ที่ใช้กับเมธอดที่ประกาศในคลาสclassmethod และ staticmethod นั้นทำให้เมธอดที่ประกาศในคลาสมีสถานะที่ต่างกันออกไป ซึ่งก็จะแบ่งออกได้เป็น ๓ รูปแบบคือ@classmethod ได้เป็นเมธอดของคลาส@staticmethod ได้เป็นเมธอดสถิตclass ClariS:
def instance_me(*arg):
return arg
@classmethod
def class_me(*arg):
return arg
@staticmethod
def static_me(*arg):
return arg
print(ClariS().instance_me('อ1','อ2')) # ได้ (<__main__.ClariS object at 0x11240f3c8>, 'อ1', 'อ2')
print(ClariS().class_me('อ1','อ2')) # ได้ (<class '__main__.ClariS'>, 'อ1', 'อ2')
print(ClariS().static_me('อ1','อ2')) # ได้ ('อ1', 'อ2')
(อินสแตนซ์, อาร์1, อาร์2, ...)(คลาส, อาร์1, อาร์2, ...)(อาร์1, อาร์2, อาร์3, ...)staticmethod แต่ไม่มี classmethodclassmethod แต่ไม่มี staticmethodclassmethod กับ staticmethod
class Clara:
@classmethod
def classme_x(self,x):
self.x = x
@staticmethod
def staticme_y(y):
Clara.y = y
classme_x เป็นเมธอดของคลาสสำหรับป้อนค่า x และ staticme_y เป็นเมธอดสถิตสำหรับป้อนค่า yclassme_x มีพารามิเตอร์มากกว่า โดยเพิ่ม self มาเป็นตัวแรก ส่วน staticme_y ไม่ต้องมีclassme_x ใช้ self ส่วน staticme_y ต้องป้อนชื่อคลาส Clara เข้าไปClara.classme_x('x ของคลาส')
Clara.staticme_y('y ของคลาส')
print('Clara.x: '+Clara.x) # ได้ Clara.x: x ของคลาส
print('Clara.y: '+Clara.y) # ได้ Clara.y: y ของคลาส
def func_z(z):
Clara.z = z
func_z('z ของคลาส')
print('Clara.z: '+Clara.z) # ได้ Clara.z: z ของคลาส
Clara.staticme_y เลย ดังนั้นเมธอดสถิตจึงเหมือนแค่เป็นการเอาฟังก์ชันธรรมดาไปยัดไว้ในคลาสclass SubClara(Clara):
0
SubClara.classme_x('x ของซับคลาส')
SubClara.staticme_y('y ของซับคลาส')
print('Clara.x: '+Clara.x) # ได้ Clara.x: x ของคลาส ***ไม่เปลี่ยนแปลง
print('Clara.y: '+Clara.y) # ได้ Clara.y: y ของซับคลาส ***มีการเปลี่ยนแปลง
print('SubClara.x: '+SubClara.x) # ได้ SubClara.x: x ของซับคลาส
print('SubClara.y: '+SubClara.y) # ได้ SubClara.y: y ของซับคลาส
SubClara เป็นซับคลาสของ Clara ซึ่งเมธอดทั้ง ๒ ของ Clara ก็จะนำมาใช้ใน SubClara ได้ด้วยx และ y จากนั้นลองมาดูผลจะพบความแตกต่างตรงที่กรณีของ y นั้นค่า y ของ Clara กลายเป็น y ของซับคลาสไปด้วยy มีการเปลี่ยนแปลงไปด้วยเพราะ staticme_y นั้นมีการใช้ชื่อ Clara แทนที่จะเป็น self ดังนั้นต่อให้รับทอดมาแล้วเมธอดนี้ก็ยังกระทำต่อคลาส Clara อยู่ดี แทนที่จะทำกับ SubClara ที่รับทอดมาy ของ Clara จึงมีการเปลี่ยนแปลงไป และค่านี้จะกลายเป็นค่า y ของ SubClara ไปด้วยclassme_x ใช้ self ดังนั้นเมื่อรับทอดไปแล้ว self ตัวนี้ก็จะหมายถึงตัวคลาสใหม่ ไม่ใช่ตัวคลาสเก่าแล้ว เมื่อใช้จึงเป็นการเปลี่ยนค่า y ของ SubClaraติดตามอัปเดตของบล็อกได้ที่แฟนเพจ