繁体   English   中英

在python中加载类后,是否可以调用函数?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM