【问题标题】:Dynamically created classes with the same name动态创建的同名类
【发布时间】:2021-12-30 12:26:51
【问题描述】:

我正在尝试使用type 在 Python 中动态创建子类:

class A:
    @classmethod
    def create_subclass(cls, name, attrs):
        return type(name, (cls,), attrs)

for i in range(5):
    x = A.create_subclass("B", {"func": abs})

print(A.__subclasses__())

这是我在输出中看到的:

[<class '__main__.B'>, <class '__main__.B'>, <class '__main__.B'>, <class '__main__.B'>, <class '__main__.B'>]

显然,这不是我的本意。 在这方面有两个问题:

  1. Python 如何处理同名的多个类?
  2. pythonic 的处理方式是什么?当然,我可以在已经存在的子类中查找名称,但是如何处理命名空间/模块?

【问题讨论】:

  • 我不完全确定,但我的猜测是,由于__subclasses__ 返回一个列表,可能以前的子类没有从那里删除,所以它们留在那里,它们也不是同一个对象,我测试过通过在字典中添加一个变量:{'var': i} 所以他们每个人都有不同的。然后我遍历返回的列表并检索了该名称,它们都有自己的值,因此它们不会被覆盖,显然也不会被删除,因此如果需要,您仍然可以使用它们,您只需要从该列表中获取它们
  • this answer
  • 名称只是与类关联的元数据。重要的是类对象本身。 A.__subclasses__() 包含对 5 个不同类的引用,这些类恰好具有相同的 __name__ 属性值。

标签: python python-3.x oop metaprogramming


【解决方案1】:

Python 不太在意类名,这些将是不同的类,您只需要有一种机制来保存和查找您想要的类。

class A:

    def __repr__(self):
        return f"{self.__class__.__name__} floor={self.floor}"


    @classmethod
    def create_subclass(cls, name, attrs):
        return type(name, (cls,), attrs)

di_cls = {}
#save them in a dictionary
for i in range(5):
    di_cls[i] = A.create_subclass("B", {"func": abs, "floor" : i})

for i, cls in di_cls.items():
    print(f"{cls()}")

class config:
    #put them in hierarchical namespaces
    cls_level1 = A.create_subclass("B", {"func": abs, "floor" : 11})

    class level2:
        cls_level2 = A.create_subclass("B", {"func": abs, "floor" : 22})

print(f"{config.cls_level1()=}")
print(f"{config.level2.cls_level2()}")

l1 = config.cls_level1()
l2 = config.level2.cls_level2()

print(f"{isinstance(l1, A)=}")
print(f"{isinstance(l2, A)=}")
print(f"{isinstance(l2, config.level2.cls_level2)=}")
print(f"{isinstance(l2, config.cls_level1)=}")


输出:

B floor=0
B floor=1
B floor=2
B floor=3
B floor=4
config.cls_level1()=B floor=11
B floor=22
isinstance(l1, A)=True
isinstance(l2, A)=True
isinstance(l2, config.level2.cls_level2)=True
isinstance(l2, config.cls_level1)=False

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-16
    • 1970-01-01
    • 2011-04-13
    • 2017-07-14
    • 2011-04-30
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多