I’m trying to dynamically create subclasses in Python with type:
JavaScript
x
10
10
1
class A:
2
@classmethod
3
def create_subclass(cls, name, attrs):
4
return type(name, (cls,), attrs)
5
6
for i in range(5):
7
x = A.create_subclass("B", {"func": abs})
8
9
print(A.__subclasses__())
10
and here’s what I see in the output:
JavaScript
1
2
1
[<class '__main__.B'>, <class '__main__.B'>, <class '__main__.B'>, <class '__main__.B'>, <class '__main__.B'>]
2
Obviously, this was not my intention. Two questions in that respect:
- How does Python handles multiple classes with identical names?
- What is a pythonic way to handle it? Of course, I can look up the name in the already existing subclasses, but then how to deal with namespaces/modules?
Advertisement
Answer
Python doesn’t care overmuch about the classname, these will be different classes, you just need to have a mechanism to save and look up the classes you want.
JavaScript
1
38
38
1
class A:
2
3
def __repr__(self):
4
return f"{self.__class__.__name__} floor={self.floor}"
5
6
7
@classmethod
8
def create_subclass(cls, name, attrs):
9
return type(name, (cls,), attrs)
10
11
di_cls = {}
12
#save them in a dictionary
13
for i in range(5):
14
di_cls[i] = A.create_subclass("B", {"func": abs, "floor" : i})
15
16
for i, cls in di_cls.items():
17
print(f"{cls()}")
18
19
class config:
20
#put them in hierarchical namespaces
21
cls_level1 = A.create_subclass("B", {"func": abs, "floor" : 11})
22
23
class level2:
24
cls_level2 = A.create_subclass("B", {"func": abs, "floor" : 22})
25
26
print(f"{config.cls_level1()=}")
27
print(f"{config.level2.cls_level2()}")
28
29
l1 = config.cls_level1()
30
l2 = config.level2.cls_level2()
31
32
print(f"{isinstance(l1, A)=}")
33
print(f"{isinstance(l2, A)=}")
34
print(f"{isinstance(l2, config.level2.cls_level2)=}")
35
print(f"{isinstance(l2, config.cls_level1)=}")
36
37
38
output:
JavaScript
1
13
13
1
B floor=0
2
B floor=1
3
B floor=2
4
B floor=3
5
B floor=4
6
config.cls_level1()=B floor=11
7
B floor=22
8
isinstance(l1, A)=True
9
isinstance(l2, A)=True
10
isinstance(l2, config.level2.cls_level2)=True
11
isinstance(l2, config.cls_level1)=False
12
13