[英]Is there a way to call a function after a class was loaded in python?
我想在类加载后将类注册到管理器,例如http处理程序注册到处理程序管理器。
它可以通过其他方式完成,例如在映射中定义关系或在类定义后调用寄存器函数。
但是,有没有更好的方法可以自动执行此操作?
更新:
沙丘的答案满足了我的需求。 我正在尝试改善这个问题,并使其对遇到相同问题的其他人更有用。
这里是例子。
处理程序/__init__.py
handler / basehandler.py-classBase,HandlerManager
handler / handlerA.py-classA(classBase)
handler / hanlderB.py-classB(classBase)
handlerA和handlerB包含classA和classB,它们是classBase的子类。
来自/ a /的classA处理程序请求,来自/ b /的classB处理程序
我需要在首次导入处理程序模块时自动将它们注册到HandlerManager。
如果“正在加载”在这里表示“正在导入”(第一次),则类装饰器是一种解决方案。 下面的示例代码是从此页面复制的
registry = {}
def register(cls):
registry[cls.__clsid__] = cls
return cls
@register
class Foo(object):
__clsid__ = "123-456"
def bar(self):
pass
我不确定您通常是初始化或调用“已加载”类的意思。
在这种情况下,将使用__init__
方法或__call__
方法。
两者都可以定义,并且可以包括在管理器中注册的调用。
类,尤其是__init__
方法, 在这里更好地描述。
小例子:
class test:
def __init__(self):
print 'I have started!'
>>> x = test()
I have started!
(只需用您的注册码替换print
。)
是的,有一种方法可以自动执行此操作。
正如Inbar所建议的那样, __init__
方法是注册对象创建的地方。
这是一个示例,可用于有效包装现有类,而不是覆盖__init__
。 在这种情况下,我为列表类做了一个包装。 通过调用super
您可以使用原始类中的初始化代码。
class nlist(list):
""" """
def __init__(self, *args, **kwargs):
print('making a new list!') # overwrite with call to a manager
super().__init__(*args)
看起来如何:
>>> list('hello')
['h', 'e', 'l', 'l', 'o']
>>> nlist('hello')
making a new list!
['h', 'e', 'l', 'l', 'o']
似乎可以用于元类。 很少需要对任何东西使用元类-它们对于几乎所有东西来说都是过分杀伤力的。 使用装饰器可以更轻松地实现使用元类可以实现的大多数功能。 但是,通过这种方式,您可以确保基本处理程序的任何子类也将自动注册(除非它要求不注册)。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.