基于类的扩展/插件库

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还是Python?   如何将java bean传递到jsp页面,以便jqQrid使用json显示?   在编译kotlin代码时,kotlin编译器如何处理java代码?   java不准确地更改JTextPane中的文本颜色   反应式编程AWS SDK v2 SdkAsyncHttpClient使用Java 11 Java实现。网http HttpClient sendAsync   在Spring AMQP中,java根据队列的消费者计数来消费队列   java在ArrayList的add()方法中创建新对象会导致内存泄漏。我能做什么不同的事?   未将java BufferedReader特定行追加到字符串   用于聊天程序格式化的java JavaFX 2文本区   java如何从netbeans项目生成exexutable文件?   swing如何在Java中使用JButton操作调整JWindow的宽度和高度?   java有没有办法在spring boot中使用jasypt aes加密和解密?   java通过使用泛型如何将映射作为集合传递给方法?   java如何替换不推荐使用的构造函数DynamoDBMapperFieldModel