反射式地在Python中创建嵌套类

反射式地在Python中创建嵌套类,python,python-3.x,reflection,inner-classes,metaclass,Python,Python 3.x,Reflection,Inner Classes,Metaclass,我试图使用3参数type函数创建嵌套的Python类。我想构造一个类似的: In [15]: class CC: ...: class DD: ...: pass ...:

我试图使用3参数
type
函数创建嵌套的Python类。我想构造一个类似的:

In [15]: class CC: 
    ...:     class DD: 
    ...:         pass 
    ...:                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
这种天真的尝试是错误的

In [17]: AA = type('AA', (), {'BB': type('BB', (), {})})                                                                                                                                                                                                                                                                                                                                                                                                                                       

但这并不完全正确,因为
BB
实际上是在外部创建的 并且在AA之前,之后才放在AA中

差异可通过以下方式证明:

In [18]: AA.BB                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
Out[18]: __main__.BB

In [16]: CC.DD                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
Out[16]: __main__.CC.DD
如何以反射/动态方式创建完全等同于嵌套定义的嵌套类


我想用它反射地生成一个
graphenesqlalchemy
api。这里的习惯用法是创建一个外部Graphene类,其中一个内部元类指向相应的SQLAchemy模型类(),例如:

上面的
User
类是一个非常简单的类,应该可以从
UserModel
类以编程方式构造。这应该适用于整个模式。

在Python 3.7文档中,它说:

[1参数]是类名,并成为
\uuu name\uuu
属性

因此,我认为您的两个示例之间的唯一区别是第一个示例中的
AA.BB.\uuuuu name.\uuuu
AA.BB
,第二个示例中的
BB
。如果希望
\uuuu名称\uuuuu
相同,可以执行以下操作:

AA = type('AA', (), {'BB': type('AA.BB', (), {})})

否则,据我所知,这两个示例在功能上是等效的。

实际上,唯一的区别是
\uuuuuu qualname\uuuu
类属性。
\uuuuu qualname\uuuu
由运行类主体的代码对象创建,并作为普通属性传递给元类
\uuuu new\uuuu
方法(通常为
type

因此,在创建类时,您只需显式地传递一个适当的
\uuuu qualname\uuuu
,即可获得此级别的等价性:

In [9]: AA = type('AA', (), {'BB': type('BB', (), {'__qualname__': 'AA.BB'})})  

In [10]: AA
Out[10]: __main__.AA

In [11]: AA.BB
Out[11]: __main__.AA.BB
这可能就足够了,但请注意,动态创建的类之间存在更细微的差异。我回答的最后一个元类问题正是关于这一点的,但采用了相反的方法:挑战在于能够真正区分使用这两种样式创建的类


(警告:这可能是我在这里给出的答案中包含的“最深的黑魔法”Python代码)

为什么要这样做?你确定这就是你问题的解决方案吗?@roganjosh相当肯定。我正在尝试以反射方式生成一个
graphenesqlalchemy
api。习惯用法是创建一个outet Graphene类,其中一个内部
Meta
类指向相应的SQLAchemy模型类@roganjosh i在问题中对用例的定义做了更全面的解释。“但这并不完全正确,因为BB实际上是在AA的外部和之前创建的,只是后来才放在AA的内部。”-CC和DD的情况几乎相同。DD在CC之前创建,并在创建CC之前插入到命名空间中。如果您使用SQLAlchemy,则需要处理奇怪的元类内容,这可能需要使用类似的内容,具体取决于所涉及的奇怪元类内容。
In [9]: AA = type('AA', (), {'BB': type('BB', (), {'__qualname__': 'AA.BB'})})  

In [10]: AA
Out[10]: __main__.AA

In [11]: AA.BB
Out[11]: __main__.AA.BB