Basically, I have a list of lists that looks like this:
lst = [['B', 'A'], ['C', 'B'], ['D', 'B'], ['E','C D'] ......]
Where t[0]
supposed to be a subclass of t[1]
(from which it inherits).
I need to write a script that creates empty classes with names matching lst
and then checks whenever a t[i-1]
is a subclass of t[i]
:
if issubclass(B, A)== True:
print('Yes')
So far, I understand how to begin and how to finish the script but I'm completely unaware how to assign a name from a list so that it would be possible to use issubclass
.
Maybe there are other ways of creating classes and tracing their inheritance?
I've just started learning classes and OOP today, so it's more than possible that I missed something crucial while dealing with this problem.
The usual way we define classes is with the class
keyword, naturally.
class B(A):
some_variable = 100
Effectively, we're constructing a new type in the Python runtime. And, in fact, types have their own constructor in Python; it's called type
and we can call it directly. The above declaration is roughly equivalent to
B = type('B', ('A',), { 'some_variable': 100 })
And now the type names are strings. There's just one more piece of the puzzle we'll need. We want to take and assign it to the name B
, using a string so we can do so with names that aren't known in advance. Assuming you want to do this at module-scope, we can use globals
, which returns a dictionary of the current module's top-level variables, which we can freely modify to add more variables. So we can do
globals()['B'] = type('B', ('A',), { 'some_variable': 100 })
Now, let's put those pieces together and write a script that uses the lst
list you suggested.
lst = [['B', 'A'], ['C', 'B'], ['D', 'B'], ['E','C D']]
# Iterate over the list.
for class_name, superclass_names in lst:
# Here, we're going to lookup all of the superclass names in the
# current global scope. It's a little more complicated than that,
# since we also want to *create* any names that don't exist (like
# 'A' in your example) when we find them.
superclasses = []
for superclass_name in superclass_names.split(' '):
# If the name doesn't exist, create it and assume its
# supertype is object, the root of Python's type hierarchy.
if superclass_name not in globals():
globals()[superclass_name] = type(superclass_name, (object,), {})
# Get the class, whether it's the one we just made or one that
# already exists.
superclasses.append(globals()[superclass_name])
# Now we construct the new class. The first argument to type() is
# the class name, the second is all of the superclasses (it must
# be a tuple, not a list, according to the documentation, so we
# convert it), and finally the contents. Since you just want the
# classes themselves, I'll assume the contents are meant to be
# empty. You can easily change that as needed.
globals()[class_name] = type(class_name, tuple(superclasses), {})
# Now let's see that everything is defined correctly. __mro__ is a
# complicated concept, but the basic idea is that it should give us E,
# followed by all of its subclasses in a reasonable order (for some
# definition of reasonable).
print(E.__mro__)