คำว่า metaprogramming หมายถึงการเขียนโปรแกรมคอมพิวเตอร์ที่โปรแกรมคอมพิวเตอร์พยายามจัดการหรือมีความรู้ในตัวเอง Python รองรับ metaprogramming สำหรับคลาสผ่านคลาสประเภทใหม่ที่เรียกว่า metaclass
การเขียนโปรแกรม Meta ผ่าน metaclasses ใน python คือการสร้างฟังก์ชันและคลาสที่จัดการโค้ดโดยการแก้ไข การตัดคำ หรือการสร้างโค้ดที่มีอยู่
คุณสมบัติหลักของ meta-programming คือ −
- เมตาคลาส
- มัณฑนากร
- คลาส-มัณฑนากร
Metaclass คืออะไร
คำจำกัดความที่จำกัดมากของ metaclass คือคลาสที่สร้างคลาส Python เป็นภาษาเชิงวัตถุที่ทุกอย่างเป็นวัตถุและคลาสก็ไม่มีข้อยกเว้น กำหนดคลาสด้วยคีย์เวิร์ดคลาส python รันคลาสจริงแล้วสร้างอ็อบเจกต์ เนื่องจากเป็นวัตถุ คุณจึงสามารถกำหนด คัดลอก เพิ่มแอตทริบิวต์ เป็นพารามิเตอร์ของฟังก์ชัน และอื่นๆ ได้ การใช้ metaclasses ช่วยให้เราควบคุมการสร้างคลาสได้ เช่น การปรับเปลี่ยนคุณสมบัติของคลาส การตรวจสอบความถูกต้องของคุณสมบัติ และอื่นๆ
Python Metaclass ในตัว
metaclass ของทุกคลาสเป็นประเภท
class a: pass print(type(a))
เอาท์พุต:
<class 'type'>
จากผลลัพธ์ข้างต้น เราจะเห็นได้ว่า “a” (คลาส) เป็นวัตถุประเภทคลาส เราสามารถพูดได้ว่า “a” (คลาส) เป็นอินสแตนซ์ของประเภทคลาส ดังนั้น type จึงเป็น metaclass ดังนั้นใน python ทุกคลาสจึงอยู่ในประเภท metaclass ในตัว
การใช้ Metaclass เพื่อสร้างคลาส python
ตามที่เราเห็นในตัวอย่างข้างต้น ประเภทคือ metaclass เริ่มต้น เราสามารถสร้างคลาสใหม่ได้โดยใช้ metaclass(type) เริ่มต้นนี้
>>> class hello(object): pass
สามารถสร้างได้ด้วยตนเองด้วยวิธีนี้เช่นกัน -
>>> hello = type('hello', (), {}) >>> print(hello)# returns a class object >>> print(hello()) # creates an instance with the class <__main__.hello object at 0x05D86830>
Type ยอมรับพจนานุกรมเพื่อกำหนดคุณสมบัติของคลาส ดังนั้น
>>> class hello(object): world = True
รหัสด้านบนคล้ายกับ
hello = type('hello', (), {'world' : True})
สร้างเมตาคลาส
ดังนั้นเมื่อใดจึงจะสร้าง metaclass? เมื่อฉันต้องการควบคุมการสร้างคลาส เช่น การตรวจสอบหรือแก้ไขคุณสมบัติของคลาส
กระบวนการสร้างอินสแตนซ์ของคลาส -
- สร้างอินสแตนซ์โดยการเรียก __new__()
- โทร __init__() เพื่อเริ่มต้นอินสแตนซ์ที่สร้างขึ้นด้านบน
ดังนั้นเมื่อเราสร้าง metaclass แบบกำหนดเอง เราจะเปลี่ยนเมธอด __new__() หรือ __init__ ของคลาสพาเรนต์
ตัวอย่างที่ 1 − Metaclass ที่แก้ไขคุณสมบัติของคลาส
class LowercaseMeta(type): def __new__(mcs, name, bases, attrs): lower_attrs = {} for k, v in attrs.items(): if not k.startswith('__'): lower_attrs[k.lower()] = v else: lower_attrs[k] = v return type.__new__(mcs, name, bases, lower_attrs) class LowercaseClass(metaclass=LowercaseMeta): BAR = True def HELLO(self): print('hello') print(dir(LowercaseClass)) LowercaseClass().hello()
ผลลัพธ์
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'bar', 'hello'] hello
Example2 − เพิ่มแอตทริบิวต์เพิ่มเติมให้กับคลาส
class ListMeta(type): def __new__(mcs, name, bases, attrs): attrs['add'] = lambda self, value: self.append(value) return type.__new__(mcs, name, bases, attrs) class MyList(list, metaclass=ListMeta): pass l = MyList() l.add(1) print(l) def class_decorator(cls): cls.add = lambda self, value: self.append(value) return cls @class_decorator class MyList(list): pass l = MyList() l.append(1) print(l)
ผลลัพธ์
[1] [1]
แอตทริบิวต์ __metaclass__
ใน python ไม่ว่าเราจะมีคลาสหรือฐานใดคลาสหนึ่งที่มีแอตทริบิวต์ __metaclass__ ก็ถือว่า metaclass อื่นเป็นประเภท metaclass เราสามารถมีแอตทริบิวต์ __metaclass__ เมื่อเราเขียนคลาสเป็น −
แล้วจะเกิดอะไรขึ้นเมื่อเรากำหนด คลาสเช่น −
class hello(object): x = 10
ด้านบน สวัสดีคลาสไม่มีแอตทริบิวต์ __metaclass__ ดังนั้นจะใช้ประเภทแทน และการสร้างคลาสจะทำเป็น −
hello = type(name, bases, dict)
ในกรณีที่สวัสดีของเรามี metaclass ที่กำหนดไว้ -
class hello(object): __metaclass__ = myMetaClass pass
ในตัวอย่างข้างต้น การสร้างคลาสทำได้โดยใช้ myMetaClass แทนประเภท สวัสดี =myMetaClass(ชื่อ, ฐาน, dict)