Python 尚未定义的代理类
考虑一个具有类似dict接口的注册表。每个键都是一个字符串名,每个值都是一个类。按此顺序使用它可以:Python 尚未定义的代理类,python,proxy-classes,Python,Proxy Classes,考虑一个具有类似dict接口的注册表。每个键都是一个字符串名,每个值都是一个类。按此顺序使用它可以: registry['foo'] = FooClass cls = registry['foo'] instance = cls 但按照这个顺序,它当然不会: cls = registry['foo'] registry['foo'] = FooClass instance = cls() 为了支持第二个用例,我对它进行了修改,但它使类变性。我的意思是这行不通: cls = registry[
registry['foo'] = FooClass
cls = registry['foo']
instance = cls
但按照这个顺序,它当然不会:
cls = registry['foo']
registry['foo'] = FooClass
instance = cls()
为了支持第二个用例,我对它进行了修改,但它使类变性。我的意思是这行不通:
cls = registry['foo']
registry['foo'] = FooClass
issubclass(cls, FooClass)
我希望支持第三种情况,因此我正在寻找一种更好的方法来代理类注册表项。有趣的问题,我将尝试以下方法:
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()
()
这确实很有趣,+1您是否考虑过隐式创建一个元类来存储信息?