Thank you all, especially @Kyle Willmon and @martineau.
I compiled your answers into an attempt here:
In vehicle.py
class Vehicle(object):
class NoAccess(Exception): pass
class Unknown(Exception): pass
@classmethod
def _get_all_subclasses(cls):
for subclass in cls.__subclasses__():
yield subclass
for subclass in subclass._get_all_subclasses():
yield subclass
@classmethod
def _get_name(cls, s):
return s.lower()
def __new__(cls, name):
name = cls._get_name(name)
for subclass in cls._get_all_subclasses():
if subclass.name == name:
# Using "object" base class method avoids recursion here.
return object.__new__(subclass)
else: # no subclass with matching name found (and no default defined)
raise Vehicle.Unknown('name "{}" has no known vehicle type'.format(name))
def drive(self):
raise NotImplementedError
In car.py
from vehicle import *
class Car(Vehicle):
name = 'car'
wheels = 4
def __init__ (self, name):
pass
def drive(self):
print('I am driving a car now, and it has ' + str(self.wheels) + ' wheels')
In truck.py
from vehicle import *
class Truck(Vehicle):
name = 'truck'
wheels = 18
def __init__(self, name):
pass
def drive(self):
print('I am driving a truck now, and it has ' + str(self.wheels) + ' wheels')
In main.py
import pkgutil
import sys
from vehicle import *
def load_all_modules_from_dir(dirname):
for importer, package_name, _ in pkgutil.iter_modules([dirname]):
if package_name not in sys.modules and package_name != 'main':
module = importer.find_module(package_name).load_module(package_name)
load_all_modules_from_dir('.')
v1 = Vehicle('car')
v1.drive()
print(type(v1))
v2 = Vehicle('truck')
v2.drive()
print(type(v2))