似乎可以用于元类。很少需要对任何事情使用元类——它们对几乎所有事情都太过分了。使用元类可以实现的大多数事情都可以使用装饰器更容易地实现。但是,通过这种方式,您可以确保您的基本处理程序的任何子类也将自动注册(除非它要求不注册)。
class HandlerManager:
handlers = []
@classmethod
def register(cls, handler):
print("registering", handler)
cls.handlers.append(handler)
class HandlerRegisterer(type):
def __init__(self, name, bases, attrs, register=True):
super().__init__(name, bases, attrs)
if register:
HandlerManager.register(self)
def __new__(metaclass, name, bases, attrs, register=True):
return super().__new__(metaclass, name, bases, attrs)
class BaseHandler(metaclass=HandlerRegisterer, register=False):
# not actually a real handler, so don't register this class
pass
class MyHandler(BaseHandler):
# only have to inherit from another handler to make sure this class
# gets registered.
pass
print(HandlerManager.handlers)
assert BaseHandler not in HandlerManager.handlers
assert MyHandler in HandlerManager.handlers
如果你需要使用抽象类,那么你需要将你的元类子类化为ABCMeta。这是因为抽象类是通过使用元类来实现的,而python只允许一个类有一个元类。通过将 ABCMeta 子类化,您可以使两个子类兼容(其中任何一个中都没有与另一个冲突的代码)。
from abc import ABC, ABCMeta, abstractmethod
class HandlerRegisterer(ABCMeta):
# subclass ABCMeta rather than type
def __init__(self, name, bases, attrs, register=True):
super().__init__(name, bases, attrs)
if register:
HandlerManager.register(self)
def __new__(metaclass, name, bases, attrs, register=True):
return super().__new__(metaclass, name, bases, attrs)
class AbstractSubHandler(MyHandler, ABC, register=False):
# not strictly necessary to subclass ABC, but nice to know it won't
# screw things up
@abstractmethod
def some_method(self):
pass
try:
AbstractSubHandler()
except TypeError:
print("Can not instantiate abstract class")
print(HandlerManager.handlers)
assert AbstractSubHandler not in HandlerManager.handlers