<p>我相信我已经成功地实现了您所要求的元类。我不确定这是否是最好的设计,但它是有效的。<code>C</code>的每个概念实例实际上都是<code>C</code>的“专门化”实例,它派生自<code>B</code>的一个专门化,它派生自一个专门化的<code>A</code>类(这些<code>A</code>类不需要以任何方式关联)。给定的<code>C</code>专用化的所有实例都将具有相同的类型,但与具有不同专门化的实例的类型不同。继承的工作方式相同,专门化定义了单独的并行类树。在</p>
<p>我的代码是:</p>
<p>首先,我们需要定义<code>A</code>类的专门化。这可以根据您的需要进行,但是在我的测试中,我使用了列表理解来在<code>num</code>类变量中构建一组具有不同名称和不同值的类。在</p>
<pre><code>As = [type('A_{}'.format(i), (object,), {"num":i}) for i in range(10)]
</code></pre>
<p>接下来,我们有一个“dummy”未专门化的<code>A</code>类,它实际上只是一个元类可以挂接的地方。<code>A</code>的元类<code>AMeta</code>执行我在上面定义的列表中指定的{<cd4>}类的查找。如果您使用不同的方法来定义专用的<code>A</code>类,请更改<code>AMeta._get_specialization</code>以找到它们。如果您愿意,甚至可以在这里按需创建<code>A</code>的新专门化。在</p>
^{pr2}$
<p>现在,我们来看看类<code>B</code>及其元类{<cd17>}。这就是我们的子类的实际专业化发生的地方。元类的<code>__call__</code>方法基于<code>selector</code>参数,使用<code>_get_specialization</code>方法来构建类的专用版本。<code>_get_specialization</code>缓存其结果,因此在继承树的给定级别上,每个专门化只生成一个类。在</p>
<p>如果需要的话,可以稍微调整一下(使用多个参数来计算<code>selector</code>),并且您可能希望将选择器传递给类构造函数,具体取决于它的实际情况。当前元类的实现只允许单一继承(一个基类),但它可能会被扩展以支持多重继承,以防您需要这种情况。在</p>
<p>注意,虽然<code>B</code>类在这里是空的,但是您可以给它在每个专门化中出现的方法和类变量(作为浅拷贝)。在</p>
<pre><code>class BMeta(AMeta):
def __new__(meta, name, bases, dct):
cls = super(BMeta, meta).__new__(meta, name, bases, dct)
cls._specializations = {}
return cls
def _get_specialization(cls, selector):
if selector not in cls._specializations:
name = "{}_{}".format(cls.__name__, selector)
bases = (cls.__bases__[0]._get_specialization(selector),)
dct = cls.__dict__.copy()
specialization = type(name, bases, dct) # not a BMeta!
cls._specializations[selector] = specialization
return cls._specializations[selector]
def __call__(cls, selector, *args, **kwargs):
cls = cls._get_specialization(selector)
return type.__call__(cls, *args, **kwargs) # selector could be passed on here
class B(A, metaclass=BMeta):
pass
</code></pre>
<p>使用此设置,用户可以定义从<code>B</code>继承的任意数量的<code>C</code>类。在幕后,他们将真正定义从<code>B</code>和{<cd4>}的各种专门化继承的一整套专门化类。在</p>
<pre><code>class C(B):
def print_num(self):
return self.num
</code></pre>
<p>需要注意的是,C从来没有真正用作常规类。<code>C</code>实际上是一个工厂,它创建各种相关类的实例,而不是自己的实例。在</p>
<pre><code>>>> C(1)
<__main__.C_1 object at 0x00000000030231D0>
>>> C(2)
<__main__.C_2 object at 0x00000000037101D0>
>>> C(1).print_num()
1
>>> C(2).print_num()
2
>>> type(C(1)) == type(C(2))
False
>>> type(C(1)) == type(C(1))
True
>>> isinstance(C(1), type(B(1)))
True
</code></pre>
<p>但是,这里有一个不明显的行为:</p>
<pre><code>>>> isinstance(C(1), C)
False
</code></pre>
<p>如果希望非专用化的<code>B</code>和<code>C</code>类型假装为其专门化的超类,可以将以下函数添加到<code>BMeta</code>:</p>
<pre><code>def __subclasscheck__(cls, subclass):
return issubclass(subclass, tuple(cls._specializations.values()))
def __instancecheck__(cls, instance):
return isinstance(instance, tuple(cls._specializations.values()))
</code></pre>
<p>这将说服内置的<code>isinstance</code>和<code>issubclass</code>函数将<code>B</code>和<code>C</code>返回的实例视为其“factory”类的实例。在</p>