使用元类的实验实用程序。
metautils3的Python项目详细描述
用于编写和组合元类的实验工具。
有关安全稳定的元类实用程序,请参见metautils
模板模型
为什么我们需要或想要编写类模板。
考虑一下这两个元类。
classAllLower(type):def__new__(mcls,name,bases,dict_):dict_={k.lower():vfork,vindict_.items()}returnsuper().__new__(mcls,name,bases,dict_)classMethodCatcher(type):def__new__(mcls,name,bases,dict_):dict_['methods']=[vforvindict_.values()ifcallable(v)]returnsuper().__new__(mcls,name,bases,dict_)
如果我们想创建一个同时使用 元类?使用同时对AllLower和 MethodCatcher不起作用,我们需要的是一种链接它们的方法。
使用类模板模型,我们可以编写我们的元类 作为:
frommetautils3importT,templatedclassAllLower(T):@templateddef__new__(mcls,name,bases,dict_):dict_={k.lower():vfork,vindict_.items()}returnsuper().__new__(mcls,name,bases,dict_)classMethodCatcher(T):@templateddef__new__(mcls,name,bases,dict_):dict_['methods']=[vforvindict_.values()ifcallable(v)];returnsuper().__new__(mcls,name,bases,dict_)
python 2样式的超级调用也可以工作,比如:super(AllLower, mcls)。 通过对^{tt4}进行delagating,我们可以在不使用super的情况下编写上述类$ 就像我们委派给一个具体的类一样,例如:
frommetautils3importT,templatedclassAllLower(T):@templateddef__new__(mcls,name,bases,dict_):dict_={k.lower():vfork,vindict_.items()}returnT.__new__(mcls,name,bases,dict_)classMethodCatcher(T):@templateddef__new__(mcls,name,bases,dict_):dict_['methods']=[vforvindict_.values()ifcallable(v)];returnT.__new__(mcls,name,bases,dict_)
在模板化函数的上下文中,Twith引用 用于实例化模板实例的类。 另一个将从您下面更改的名称是类名 本身。当您处于方法的上下文中时,类名实际上 分解为具体类型。
现在我们可以定义使用这些元类的both的类,如下所示:
classC(object,metaclass=MethodCatcher(AllLower())):defF():passdefg():passa='a'B='b'
我们可以看到这应用了元类的组成。
>>>C.f<function__main__.C.F>>>>C.g<function__main__.C.g>>>>C.b'b'>>>C.a'a'>>>C.methods[<function__main__.C.g>,<function__main__.C.F>]
元类的组成顺序是显式的,因为它们充当 变形金刚之间。
Template
虽然前面的示例只显示了元类,但是您可以将其用于 类;但是,对于具有兼容的 元类层次结构很重要。
Template是一个可调用的,它接受一个type对象并 返回一个新的type对象。它接受以下参数:
- base:类型对象。default:type。
- adjust_name:我们是否应该在 新类型对象。default:True。
它们可以和任何一个混凝土元类连接在一起, 例如:
new_class=m(n,p(q(...z(type)...)))
您也可以使用compose函数来执行此操作:
frommetautils3importcomposenew_class_template=compose(m,n,p,q,...,z)
与metautils
的差异metautils3使用了更多的实验特性,包括字节码和代码 允许隐式完成更多工作的对象转换。这是 T对象如何引用方法内部的模板参数,或 如何让super按预期工作。此包还调用 ctypes和其他特定于cpython的代码,使其更不可移植 难以维持。这主要是一个有趣的概念证明 metautils到极限。对于任何生产代码,我都必须向您推荐 使用更稳定的版本。