============================ 9.15 定义有å¯é€‰å‚数的元类 ============================ ---------- 问题 ---------- ä½ æƒ³å®šä¹‰ä¸€ä¸ªå…ƒç±»ï¼Œå…许类定义时æä¾›å¯é€‰å‚æ•°ï¼Œè¿™æ ·å¯ä»¥æŽ§åˆ¶æˆ–é…置类型的创建过程。 ---------- 解决方案 ---------- 在定义类的时候,Pythonå…许我们使用 ``metaclass``关键å—傿•°æ¥æŒ‡å®šç‰¹å®šçš„元类。 例如使用抽象基类: .. code-block:: python from abc import ABCMeta, abstractmethod class IStream(metaclass=ABCMeta): @abstractmethod def read(self, maxsize=None): pass @abstractmethod def write(self, data): pass ç„¶è€Œï¼Œåœ¨è‡ªå®šä¹‰å…ƒç±»ä¸æˆ‘们还å¯ä»¥æä¾›å…¶ä»–的关键å—傿•°ï¼Œå¦‚下所示: .. code-block:: python class Spam(metaclass=MyMeta, debug=True, synchronize=True): pass 为了使元类支æŒè¿™äº›å…³é”®å—傿•°ï¼Œä½ 必须确ä¿åœ¨ ``__prepare__()`` , ``__new__()`` å’Œ ``__init__()`` æ–¹æ³•ä¸ éƒ½ä½¿ç”¨å¼ºåˆ¶å…³é”®å—傿•°ã€‚å°±åƒä¸‹é¢è¿™æ ·ï¼š .. code-block:: python class MyMeta(type): # Optional @classmethod def __prepare__(cls, name, bases, *, debug=False, synchronize=False): # Custom processing pass return super().__prepare__(name, bases) # Required def __new__(cls, name, bases, ns, *, debug=False, synchronize=False): # Custom processing pass return super().__new__(cls, name, bases, ns) # Required def __init__(self, name, bases, ns, *, debug=False, synchronize=False): # Custom processing pass super().__init__(name, bases, ns) ---------- 讨论 ---------- ç»™ä¸€ä¸ªå…ƒç±»æ·»åŠ å¯é€‰å…³é”®å—傿•°éœ€è¦ä½ 完全弄懂类创建的所有æ¥éª¤ï¼Œ å› ä¸ºè¿™äº›å‚æ•°ä¼šè¢«ä¼ 递给æ¯ä¸€ä¸ªç›¸å…³çš„æ–¹æ³•。 ``__prepare__()`` 方法在所有类定义开始执行å‰é¦–先被调用,用æ¥åˆ›å»ºç±»å‘½å空间。 通常æ¥è®²ï¼Œè¿™ä¸ªæ–¹æ³•åªæ˜¯ç®€å•的返回一个å—å…¸æˆ–å…¶ä»–æ˜ å°„å¯¹è±¡ã€‚ ``__new__()`` 方法被用æ¥å®žä¾‹åŒ–最终的类对象。它在类的主体被执行完åŽå¼€å§‹æ‰§è¡Œã€‚ ``__init__()`` 方法最åŽè¢«è°ƒç”¨ï¼Œç”¨æ¥æ‰§è¡Œå…¶ä»–的一些åˆå§‹åŒ–工作。 å½“æˆ‘ä»¬æž„é€ å…ƒç±»çš„æ—¶å€™ï¼Œé€šå¸¸åªéœ€è¦å®šä¹‰ä¸€ä¸ª ``__new__()`` 或 ``__init__()`` æ–¹æ³•ï¼Œä½†ä¸æ˜¯ä¸¤ä¸ªéƒ½å®šä¹‰ã€‚ ä½†æ˜¯ï¼Œå¦‚æžœéœ€è¦æŽ¥å—其他的关键å—傿•°çš„è¯ï¼Œè¿™ä¸¤ä¸ªæ–¹æ³•å°±è¦åŒæ—¶æä¾›ï¼Œå¹¶ä¸”éƒ½è¦æä¾›å¯¹åº”çš„å‚æ•°ç¾å。 默认的 ``__prepare__()`` 方法接å—ä»»æ„的关键å—傿•°ï¼Œä½†æ˜¯ä¼šå¿½ç•¥å®ƒä»¬ï¼Œ æ‰€ä»¥åªæœ‰å½“这些é¢å¤–çš„å‚æ•°å¯èƒ½ä¼šå½±å“到类命åç©ºé—´çš„åˆ›å»ºæ—¶ä½ æ‰éœ€è¦åŽ»å®šä¹‰ ``__prepare__()`` 方法。 通过使用强制关键å—傿•°ï¼Œåœ¨ç±»çš„åˆ›å»ºè¿‡ç¨‹ä¸æˆ‘ä»¬å¿…é¡»é€šè¿‡å…³é”®å—æ¥æŒ‡å®šè¿™äº›å‚数。 使用关键å—傿•°é…置一个元类还å¯ä»¥è§†ä½œå¯¹ç±»å˜é‡çš„ä¸€ç§æ›¿ä»£æ–¹å¼ã€‚例如: .. code-block:: python class Spam(metaclass=MyMeta): debug = True synchronize = True pass å°†è¿™äº›å±žæ€§å®šä¹‰ä¸ºå‚æ•°çš„好处在于它们ä¸ä¼šæ±¡æŸ“类的å称空间, 这些属性仅仅åªä»Žå±žäºŽç±»çš„åˆ›å»ºé˜¶æ®µï¼Œè€Œä¸æ˜¯ç±»ä¸çš„è¯å¥æ‰§è¡Œé˜¶æ®µã€‚ å¦å¤–,它们在 ``__prepare__()`` æ–¹æ³•ä¸æ˜¯å¯ä»¥è¢«è®¿é—®çš„ï¼Œå› ä¸ºè¿™ä¸ªæ–¹æ³•ä¼šåœ¨æ‰€æœ‰ç±»ä¸»ä½“æ‰§è¡Œå‰è¢«æ‰§è¡Œã€‚ 但是类å˜é‡åªèƒ½åœ¨å…ƒç±»çš„ ``__new__()`` å’Œ ``__init__()`` 方法ä¸å¯è§ã€‚