classmethod
และ staticmethod
ซึ่งเป็นฟังก์ชันมาตรฐานที่นิยมนำมาใช้เพื่อตกแต่งเมธอดภายในคลาสclassmethod
def
จากนั้นก็ใช้ 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
นั่นคือ staticmethod
staticmethod
มีไว้สร้างสิ่งที่เรียกว่าเมธอดสถิต การใช้งาน 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
แต่ไม่มี classmethod
classmethod
แต่ไม่มี staticmethod
classmethod
กับ 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
เป็นเมธอดสถิตสำหรับป้อนค่า y
classme_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
ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ