反射式地在Python中创建嵌套类
我试图使用3参数反射式地在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 ...:
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