用于与元类一起工作的实验性实用工具。
项目描述
用于编写和组合元类的实验性实用工具。
有关安全稳定的元类实用工具,请参阅metautils
模板模型
我们为什么需要或想要编写类模板。
考虑这两个元类。
class AllLower(type):
def __new__(mcls, name, bases, dict_):
dict_ = {k.lower(): v for k, v in dict_.items()}
return super().__new__(mcls, name, bases, dict_)
class MethodCatcher(type):
def __new__(mcls, name, bases, dict_):
dict_['methods'] = [v for v in dict_.values() if callable(v)]
return super().__new__(mcls, name, bases, dict_)
如果我们想创建一个使用这两个元类的类,我们应该怎么办?使用同时继承自AllLower和MethodCatcher的类不起作用,我们想要的链式连接方式。
使用类模板模型,我们可以将元类编写为
from metautils3 import T, templated
class AllLower(T):
@templated
def __new__(mcls, name, bases, dict_):
dict_ = {k.lower(): v for k, v in dict_.items()}
return super().__new__(mcls, name, bases, dict_)
class MethodCatcher(T):
@templated
def __new__(mcls, name, bases, dict_):
dict_['methods'] = [v for v in dict_.values() if callable(v)];
return super().__new__(mcls, name, bases, dict_)
Python 2风格的super调用也将工作,例如:super(AllLower, mcls)。我们可以像委托给具体类一样,通过委托给T来编写上述类,例如
from metautils3 import T, templated
class AllLower(T):
@templated
def __new__(mcls, name, bases, dict_):
dict_ = {k.lower(): v for k, v in dict_.items()}
return T.__new__(mcls, name, bases, dict_)
class MethodCatcher(T):
@templated
def __new__(mcls, name, bases, dict_):
dict_['methods'] = [v for v in dict_.values() if callable(v)];
return T.__new__(mcls, name, bases, dict_)
在模板函数的上下文中,T将指向用于实例化模板实例的具体类。另一个将更替的名字是类名本身。当你在方法的上下文中时,类名实际上会解析为具体类型。
现在我们可以定义使用这两个元类的类,如下所示
class C(object, metaclass=MethodCatcher(AllLower())):
def F():
pass
def g():
pass
a = '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>]
元类组合的顺序是明确的,因为它们作为相互的转换器。
模板
虽然前面的例子只展示了元类,但您可以用这个方法为任何类使用;然而,它对于需要具有兼容元类层次结构的元类来说最为有用。
模板是一个可调用的函数,它接受一个类型对象并返回一个新的类型对象。它接受以下参数
base:一个类型对象。 默认值: type。
adjust_name:是否在新的类型对象前添加基本名称。 默认值: True。
这些可以与任何具体元类一起链式调用,例如
new_class = m(n,p(q(...z(type)...)))
您还可以使用组合函数来完成此操作
from metautils3 import compose
new_class_template = compose(m, n, p, q, ..., z)
与 metautils 的区别
metautils3使用了更多实验性功能,包括字节码和代码对象转换,这允许进行更多隐式的工作。这就是 T 对象如何在方法内部引用模板参数的原因,或者这就是我们如何使 super 正确工作。此包还调用 ctypes 和其他 CPython 特定代码,使其不太便携且难以维护。这主要是一个有趣的证明概念,以推动 metautils 的极限。对于任何生产代码,我必须推荐您使用更稳定的版本。
项目详情
metautils3-0.1.2.tar.gz 的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | 1c2c3d33f1146c7cf763d88b1a7497d0cf5d55f25352a38579d61e2e3ec7c255 |
|
MD5 | e95893a22e1b525e6eeb89172515ae0e |
|
BLAKE2b-256 | 469726574000f63defafc91775d2f9b8fe2deca65e42bbc078c29dcaff03a384 |