反思地在Python中创建嵌套类

时间:2018-11-27 20:30:08

标签: python python-3.x reflection inner-classes metaclass

我正在尝试使用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

如何反射/动态创建完全等同于嵌套定义的嵌套类?


我想用它来反射性地生成graphene-sqlalchemy api。习惯用法是创建一个外部Graphene类,并使用一个内部Meta类指向相应的SQLAchemy模型类(http://docs.graphene-python.org/projects/sqlalchemy/en/latest/tutorial/#schema),例如:

from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import relationship

from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class UserModel(Base):
    __tablename__ = 'department'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    last_name = Column(String)

from graphene_sqlalchemy import SQLAlchemyObjectType

class User(SQLAlchemyObjectType):
    class Meta:
        model = UserModel
        # only return specified fields
        only_fields = ("name",)
        # exclude specified fields
        exclude_fields = ("last_name",)

上面的User类是一个不错的cookie切割器,应该可以从UserModel类以编程方式构造。然后,这应该对整个架构都是可行的。

2 个答案:

答案 0 :(得分:2)

在Python 3.7 type文档中,它表示:

  

[第一个参数]是类名称,并成为__name__属性。

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

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

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

答案 1 :(得分:2)

实际上,您得到的唯一区别是__qualname__类属性。 __qualname__由运行类主体的代码对象创建,并作为普通属性传递给元类__new__方法(通常为type)。

因此,要达到此等价水平,只需在创建类时显式传递正确的__qualname__

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

这对您来说可能就足够了,但是请注意,动态创建的类之间存在更多细微的差异。我回答的最后一个元类问题恰好与此有关,但是采用了相反的方法:挑战在于实际上是否能够区分使用两种样式创建的类。

Detect if class was defined declarative or functional - possible?

(警告:其中包含我在此处回答过的“最深的黑魔法” Python代码)