尚未定义的代理类

2024-09-26 17:58:32 发布

您现在位置:Python中文网/ 问答频道 /正文

考虑一个具有类似dict接口的注册表。每个键都是一个字符串名,每个值都是一个类。按以下顺序使用:

registry['foo'] = FooClass
cls = registry['foo']
instance = cls

但按照这个顺序,它当然不会:

cls = registry['foo']
registry['foo'] = FooClass
instance = cls()

为了支持第二个用例,Iimplemented a class constructor wrapper in a function但是它“变性”了类。我的意思是这行不通:

cls = registry['foo']
registry['foo'] = FooClass
issubclass(cls, FooClass)

我想支持第三种情况,所以我正在寻找一种更好的方法来代理类注册表项。你知道吗


Tags: instance字符串infoo顺序注册表用例wrapper
1条回答
网友
1楼 · 发布于 2024-09-26 17:58:32

有趣的问题,我会尝试这样的方法:

from abc import ABCMeta


class Registry(object):

    def __init__(self):
        self._proxies = {}
        self._classes = {}

    def resolve(self, name):
        try:
            return self._classes[name]
        except KeyError:
            raise KeyError('Cannot resolve "%s".'
                           ' Class not registered yet.' % name)

    def __getitem__(self, name):
        """Return a proxy class bound to `name`."""
        if name not in self._proxies:
            self._proxies[name] = make_proxy(lambda: self.resolve(name))
        return self._proxies[name]

    def __setitem__(self, name, val):
        """Store a class for `name`."""
        self._classes[name] = val


def make_proxy(resolve):
    """
    Return a proxy class.

    :param resolve: a function that returns the actual class

    """

    class ProxyMeta(ABCMeta):
        """
        Custom meta class based on ABCMeta that forwards various checks
        to the resolved class.

        """
        def __eq__(self, y):
            return resolve() == y

        def __repr__(self):
            return repr(resolve())

        def __str__(self):
            return str(resolve())

    class Proxy(object):
        """
        The actual proxy class.

        """
        __metaclass__ = ProxyMeta

        def __new__(cls, *args, **kwargs):
            """Calling this class returns an instance of the resolved class."""
            return resolve()(*args, **kwargs)

        @classmethod
        def __subclasshook__(cls, subclass):
            """issubclass() overwrite."""
            return issubclass(resolve(), subclass)

    return Proxy

>>> registry = Registry()
>>> List = registry['list']
>>> List
KeyError: 'Cannot resolve "list". Class not registered yet.'
>>> registry['list'] = list
>>> List
<type 'list'>
>>> issubclass(List, List)
True
>>> issubclass(list, List)
True
>>> List == list
True
>>> List()
[]
>>> registry['list'] = tuple
>>> List()
()

相关问题 更多 >

    热门问题