基于类的扩展/插件库

extend_me的Python项目详细描述


扩展我-基于类的扩展/插件库

此模块提供应用程序的扩展机制 基于"通过继承扩展"。我的意思是 能够简单地定义应用程序对象的新扩展 通过对应用程序的可扩展类进行子类化。

例如,我们有一个带"worker"类的应用程序 使可扩展(允许第三方模块扩展或 改变它的行为)。思维狭隘,工作很多 要做到的是,对加载、登记的推动机制, 结束启用扩展,使用大量粘合代码,必须定义 一些连接扩展和主应用程序的入口点。但为什么不呢? 假设"worker"的任何子类 扩展它?这个模块提供了 有两种方式:

    < DL>
    显式(通过直接使用元类 可扩展类型
    > UL>
  • 当你用这种方法时,你将拥有单独的基类 由扩展类和类getter子类 它将基于所有定义的扩展来构造类 使用多个inhertance
< DL>
隐式(通过使用隐式使用元类魔术的可扩展类)
> UL> < DL>
可扩展的 类负责所有的元类魔术
与正确类的生成对象相关

工作原理

元类( extensibletype )跟踪类it的所有子类 应用于,并提供基于 基类的子类,因此使用 子类。因此正确类的生成是一个独立的过程 应该在需要可扩展类的地方使用它。

为了简化这个类,实现了可扩展类。它重新定义了 方法自动创建正确类的实例 (继承自基类及其所有扩展的类)

示例

可扩展类型

一开始我们应该创建一个自动 获取所有扩展的所有信息,并应用此元类 要分类,我们希望启用扩展:

>>> import six  # Used for Python 2/3 compatability
>>> mc = ExtensibleType._("Object")

>>> @six.add_metaclass(mc)
... class Object(object):
...     pass

不是可扩展类型的方法。此方法用于创建元类 对于特定对象。它接收一个参数字符串,该字符串将用作 此元类生成的类的名称

接下来我们可以定义这个类的扩展。很简单。 只是子类以前定义的类:

>>> class ObjectExtension(Object):
...     cool_attribute = 1
...     def method1(self):
...         return "Test"

所以…现在我们有基类和扩展。这就是 核心魔法出现。在automaticaly开始时创建的元类 收集基类的所有子类。所以现在可以创造新的 类是子类使用多重继承的基类的所有子类的。 元类mc会帮你做到的:

>>> cls = mc.get_class()

现在您可以根据需要使用cls,而不是基类。 它可以完成基类所能做的一切,以及扩展所能做的一切:

>>> obj = cls()
>>> obj.method1()
'Test'
>>> obj.cool_attribute
1

可扩展的ByHashType

extensibletype 相同,但允许构建类树 用于不同的名称(类型)。请看下面的示例。

首先,创建指定继承规则的元类:

>>> import six  # Used for Python 2/3 compatability
>>> mc = ExtensibleByHashType._("Connector", hashattr='name')

这里我们看到的是方法中的附加参数: hashattr='name' 它描述了将哪些元属性用作键(散列)。

下一步-我们必须用这个元类创建基类。 例如,我们将研究 openerproxy 项目的连接类:

>>> @six.add_metaclass(mc)
... class ConnectorBase(object):
...     # Base class for all connectors
...
...     def __init__(self, host, port, verbose=False):
...         self.host = host
...         self.port = port
...         self.verbose = verbose
...
...     def _get_service(self, name):
...         raise NotImplementedError
...
...     def get_service(self, name):
...         # Returns service for specified *name*
...         return self._get_service(name)

基类只描述接口,可能是抽象逻辑的一部分 下一步我们将以不同的方式扩展它以支持不同的 连接类型:

>>> class ConnectorXMLRPC(ConnectorBase):
...     # XML-RPC connector
...     class Meta:
...         name = 'xml-rpc' # remember definition of metaclass?
...                          # this attribute is used as hash(key)
...                          # to unique identify each banch of extensions
...                          # of base class
...
...     def __init__(self, *args, **kwargs):
...         super(ConnectorXMLRPC, self).__init__(*args, **kwargs)
...         self.__services = {}
...
...     def get_service_url(self, service_name):
...         return 'http://%s:%s/xmlrpc/%s' % (self.host, self.port, service_name)
...
...     def _get_service(self, name):
...         service = self.__services.get(name, False)
...         if service is False:
...             service = XMLRPCProxy(self.get_service_url(name), verbose=self.verbose)
...             self.__services[name] = service
...         return service
...
...
... # Pay attention on base class.
>>> class ConnectorXMLRPCS(ConnectorXMLRPC):
...     # XML-RPCS Connector
...     class Meta:
...         name = 'xml-rpcs'
...
...     def get_service_url(self, service_name):
...         return 'https://%s:%s/xmlrpc/%s' % (self.host, self.port, service_name)

上面的代码创建了两个连接器:一个用于 xml-rpc ,另一个用于 xml-rpcs 。 每个连接器都可以通过简单的继承来扩展。如果需要的话 扩展可以定义新的分支(键)(散列),如上文示例所示。

要使用此连接器,mc 有方法 获取类(name[,default=false]) wich将返回为hash=*name*:

生成的类
>>> cls = mc.get_class('xml-rpc')
>>> [b.__name__ for b in cls.__bases__]
['ConnectorXMLRPC', 'ConnectorBase']
>>> cls.__name__
'Connector'

>>> cls = mc.get_class('xml-rpcs')
>>> [b.__name__ for b in cls.__bases__]
['ConnectorXMLRPCS', 'ConnectorBase']
>>> cls.__name__
'Connector'

上面的示例显示将为指定的名称生成哪些类。 默认情况下,如果使用未注册的名称调用mc.get_class (未定义扩展名meta.name==name)它将引发 valueerror

如果要允许创建未定义meta.name 的类, 只需将 default=true 传递到 mc。获取类:

>>> cls = mc.get_class('unexisting-protocol', default=True)
>>> [b.__name__ for b in cls.__bases__]
['ConnectorBase']
>>> cls.__name__
'Connector'

可扩展

这个类提供了一个更高层次的抽象,允许隐藏所有的元类魔术 看在眼前。所以,使用它不需要担心元类和类 创建过程。从基类继承扩展,并在程序中使用 基类的实例。让我们在示例中看到它:

>>> import six  # Used for Python 2/3 compatability
>>> mc = ExtensibleType._("Object")

>>> @six.add_metaclass(mc)
... class Object(object):
...     pass
0

现在只要使用基类的实例,就可以使用扩展提供的所有功能:

>>> import six  # Used for Python 2/3 compatability
>>> mc = ExtensibleType._("Object")

>>> @six.add_metaclass(mc)
... class Object(object):
...     pass
1

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
Java流收集组合器   文件如何在java中逐个压缩选定的多个文件夹   从Google存储下载数据时发生java SocketTimeoutException   java在安卓应用程序客户端上从python服务器接收值,然后显示与该值对应的mysql数据   数组如何在Java中测试字符串索引是否为Null   java将一串值拆分并放入一个表中   java Spring Memcached注释不缓存   调用pom中设置的环境变量时出现java问题。xml surefire插件   java修复JFrame中重叠的鼠标侦听器   格式化java。sql。日期至yyyyMMdd   java声音剪辑。如果剪辑不正确,isActive应返回true。启动被调用   无根计算机上hadoop中的java格式化namenode   从字符串数组中删除重复项,而无需在Java中进行显式比较   java Eclipse插件安装错误   java webdriver无法在firefox中单击超链接   动画错误。朗。反思。调用目标异常   java试图调用虚拟方法“void”。小装置。编辑文本。在空对象引用上添加TextChangedListener(安卓.text.TextWatcher)”