การสร้างคลาสของ Python
ทำความเข้าใจ type เมตาคลาสเริ่มต้น และฮุกการสร้างคลาส
การสร้างคลาสของ Python เป็นบทเรียน Python Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Python Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Python Academy มีบทเรียนทั้งหมด 4 บทเรียน
type() คือเมตาคลาส
ทุกคลาสใน Python เป็นอินสแตนซ์ของ type โดย type เองก็เป็นคลาส และเป็นเมตาคลาสของเมตาคลาสทั้งหมด
# These are equivalent:
class Dog:
sound = "woof"
Dog2 = type("Dog2", (), {"sound": "woof"})
print(type(Dog)) # <class 'type'>
print(type(Dog2)) # <class 'type'>รูปแบบสามอาร์กิวเมนต์ของ type()
type(name, bases, namespace) สร้างคลาสใหม่แบบไดนามิก ซึ่งเป็นสิ่งเดียวกับที่คำสั่งประกาศคลาสทำอยู่เบื้องหลัง
Animal = type("Animal", (), {"speak": lambda self: "..."})
Dog = type("Dog", (Animal,), {"speak": lambda self: "woof"})
d = Dog()
print(d.speak()) # woofขั้นตอนการสร้างคลาส
เมื่อ Python พบคำสั่งประกาศคลาส จะดำเนินการดังนี้ 1) แก้ไขเมตาคลาส 2) เตรียมเนมสเปซ 3) ดำเนินการเนื้อหาของคลาส 4) เรียก metaclass(name, bases, namespace)
# class Foo(Base, metaclass=Meta):
# x = 1
#
# Equivalent to:
# namespace = Meta.__prepare__("Foo", (Base,))
# exec(class_body, namespace)
# Foo = Meta("Foo", (Base,), namespace)__prepare__
__prepare__(name, bases, **kw) เป็นเมธอดของคลาสบนเมตาคลาส ซึ่งคืนค่าดิกชันนารีเนมสเปซที่ใช้ระหว่างดำเนินการเนื้อหาของคลาส คุณสามารถเขียนทับเมธอดนี้เพื่อใช้ OrderedDict หรือการแมปแบบกำหนดเองได้
class OrderedMeta(type):
@classmethod
def __prepare__(mcs, name, bases, **kw):
print(f"Preparing namespace for {name}")
return {}
class MyClass(metaclass=OrderedMeta):
x = 1
y = 2__new__ เทียบกับ __init__ ใน type
type.__new__ สร้างอ็อบเจ็กต์คลาส ส่วน type.__init__ เริ่มต้นการทำงานของอ็อบเจ็กต์นั้น สำหรับเมตาคลาส ให้เขียนทับ __new__ เพื่อปรับแต่งการสร้างคลาส
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kw):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kw)
return cls._instances[cls]
class DB(metaclass=Singleton):
pass
print(DB() is DB()) # Trueตัวตกแต่งคลาสเทียบกับเมตาคลาส
ตัวตกแต่งคลาสทำงานหลังการสร้างคลาส ส่วนเมตาคลาสควบคุมกระบวนการสร้างเอง หากต้องการเพิ่มความสามารถอย่างง่าย ให้เลือกใช้ตัวตกแต่ง แต่ให้ใช้เมตาคลาสเมื่อจำเป็นต้องเปลี่ยนแปลงกระบวนการสร้าง
def add_repr(cls):
cls.__repr__ = lambda self: f"{cls.__name__}()"
return cls
@add_repr
class Widget:
pass
print(Widget()) # Widget()__init_subclass__
__init_subclass__ จะถูกเรียกบนคลาสฐานทุกครั้งที่มีการกำหนดคลาสย่อย เป็นทางเลือกที่มีน้ำหนักเบากว่าเมตาคลาสสำหรับปรับแต่งการทำงานของคลาสย่อย
class Plugin:
_registry = []
def __init_subclass__(cls, **kw):
super().__init_subclass__(**kw)
Plugin._registry.append(cls)
class AudioPlugin(Plugin): pass
class VideoPlugin(Plugin): pass
print(Plugin._registry) # [AudioPlugin, VideoPlugin]ABCMeta
ABCMeta เป็นเมตาคลาสในตัวที่ทำให้คลาสฐานนามธรรมทำงานผ่าน @abstractmethod
from abc import ABCMeta, abstractmethod
class Shape(metaclass=ABCMeta):
@abstractmethod
def area(self): ...
class Circle(Shape):
def __init__(self, r): self.r = r
def area(self): return 3.14159 * self.r ** 2
# Shape() # TypeError: Can't instantiate abstract classการตรวจสอบเมตาคลาสของคลาส
ใช้ type(cls) เพื่อค้นหาเมตาคลาสของคลาส และใช้ cls.__mro__ เพื่อดูลำดับการค้นหาเมธอด
class Meta(type): pass
class Foo(metaclass=Meta): pass
print(type(Foo)) # <class '__main__.Meta'>
print(Foo.__mro__) # (Foo, object)การสืบทอดเมตาคลาส
เมตาคลาสของคลาสจะถูกสืบทอดไปยังคลาสย่อย หากคลาสฐานสองคลาสมีเมตาคลาสแตกต่างกัน จะต้องใช้เมตาคลาสที่สืบทอดลงมามากที่สุด มิฉะนั้นจะเกิดข้อขัดแย้ง
class MyMeta(type): pass
class Base(metaclass=MyMeta): pass
class Child(Base): pass # Child's metaclass is also MyMeta
print(type(Child)) # <class '__main__.MyMeta'>ควรใช้เมตาคลาสเมื่อใด
ใช้เมตาคลาสสำหรับการลงทะเบียนคลาสย่อยโดยอัตโนมัติ การบังคับใช้เงื่อนไขคงที่ของคลาส การตรวจจับฟิลด์ของ ORM เช่น Model ของ Django และการกำหนดเส้นทางของเฟรมเวิร์กส่วนเชื่อมต่อโปรแกรมประยุกต์ ในกรณีส่วนใหญ่ ให้ใช้ __init_subclass__ หรือตัวตกแต่งคลาสแทน
# Real-world: Django ORM uses ModelBase metaclass
# to collect field definitions into _meta
# You rarely need a custom metaclass;
# __init_subclass__ covers most plugin/registration patternsตรวจสอบความเข้าใจอย่างรวดเร็ว
type("Dog", (Animal,), {"speak": lambda self: "woof"}) ทำอะไร
สรุปทบทวน
ทุกคลาสเป็นอินสแตนซ์ของ type กระบวนการสร้างคลาสมีดังนี้ แก้ไขเมตาคลาส → เตรียมเนมสเปซ → ดำเนินการเนื้อหา → เรียกเมตาคลาส เลือกใช้ __init_subclass__ สำหรับจุดเชื่อมต่อของคลาสย่อยอย่างง่าย และใช้เมตาคลาสเต็มรูปแบบเฉพาะเมื่อต้องควบคุมการสร้างคลาสเอง
คำถามที่พบบ่อย
บทเรียน “การสร้างคลาสของ Python” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การสร้างคลาสของ Python” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Python Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Python Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การสร้างคลาสของ Python”
ทำความเข้าใจ type เมตาคลาสเริ่มต้น และฮุกการสร้างคลาส คุณปฏิบัติ Python Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Python Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Python Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “การสร้างคลาสของ Python” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Python Academy นี้ได้ไหม
ได้ บทเรียน Python Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การสร้างคลาสของ Python
- การเขียนเมตาคลาสแบบกำหนดเอง
- ตัวบอกคุณสมบัติ: __get__, __set__, __delete__
- __slots__ และการเพิ่มประสิทธิภาพหน่วยความจำ