Contiuing from this post: Dynamically creating a class from file, type(name, bases, dict) can be used to dynamically create a class with name name, with base classes bases, and attributes dict.
I have classes such as:
class City:
def __init__(self):
self.name = 0
class Building:
def __init__(self):
self.number = 100
I want to create a new class from a string (for ex. "School"), which inherits from the above classes. I have done:
School = type("School", (City, Building), {"school_name": "abc"}
s = School()
hasattr(s, "school_name") gives True. However, hasattr(s, "name") gives False.
How can I make sure that:
- My dynamically generated class
Schoolinherits the attributes of its base class(es)? - How can I add additional attributes to the class
Schoolafter already creating the classSchool = type("School", (Building, Home), {"school_name": "abc"}? (Suppose I want to add two new attributes (address,pincode) to the class later on in my script - can I do that?)
CodePudding user response:
When you create a class dynamically you can also pass methods, "constructor" __init__ included.
For a class with single parent:
# methods & attrs
d = {"school_name": 'abc',
'__init__': lambda self, *args, **kwargs:
super(type(self), self).__init__(*args, **kwargs)}
# dynamic class
School = type("School", (City,), d)
# instance
s = School()
print(hasattr(s, 'name'))
#True
print(s.school_name)
#abc
For a class with two parents:
d = {"school_name": 'abc',
'__init__': lambda self, *args, **kwargs:
(City.__init__(self, *args, **kwargs),
Building.__init__(self, *args, **kwargs))[0]
}
School = type("School", (City, Building), d)
s = School()
print(hasattr(s, 'name'))
#True
print(hasattr(s, 'number'))
#True
The __init__ is called explicitly for each parent. For more complex stuffs I recommend to write a classical function instead of lambdas.
For a class with two parents, base class-free version:
d = {"school_name": 'abc',
'__init__': lambda self, *args, **kwargs:
[cls.__init__(self, *args, **kwargs) for cls in type(self).__bases__][0]
}
NOTE if dealing with multiple inheritance where parents classes have different signatures (so the parameters of __init__) it could be a big mess if don't pay attention to *args & **kwargs!
CodePudding user response:
City’s init method gets override by Building’s init method try
hasattr(s, ‘number’)
and it should return True.
Define your class as
class City:
name = 0
class Building:
number = 100
This way attributes can be inherited.
For the second question, not sure about what you are asking for, but try
School.address = ‘foo’
School.pincode = ‘bar’
