Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

การเขียนโปรแกรม Meta ด้วย Metaclasses ใน Python


คำว่า 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 ในตัว

การเขียนโปรแกรม Meta ด้วย Metaclasses ใน Python

การใช้ 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)