How do I instantiate a class based on a variable?

Hi all. I’m a long-time Perl developer, porting some stuff to Python. I need a constructor or factory to be able to return a subclass, based on the database type in a connection object passed in ( there are a LOT of other things also being passed in ). I have the detection of the database type working ( kind of ). In Perl, I’d then just concatenate things, like:

sub generate_subclass {
    my $connection  = shift; # pull the connection object *ONLY*
    my $database_type = get_database_type( $connection );
    my $target_class_type = $database_type . 'myclass';
    return $target_class_type->new( $connection , @_ ); # pass all other args into target constructor
}

Is there a way to instantiate a class based on a variable, as in the “return” line, above?

By Dan Kasak via Discussions on Python.org at 12Sep2022 06:52:

Hi all. I’m a long-time Perl developer, porting some stuff to Python. I
need a constructor or factory to be able to return a subclass, based on
the database type in a connection object passed in […]

I wrote one of these just today!

 def TypedKeyClass(key_type, superclass, name=None):
   ''' Factory to create a new mapping class subclassing
       `(TypedKeyMixin,superclass)` which checks that keys are of type
       `key_type`.
   '''

   class TypedKeyMapping(TypedKeyMixin, superclass):

     def __init__(self, *a, **kw):
       ''' Initialise the `TypedKeyDict`. The first positional parameter
           is the type for keys.
       '''
       TypedKeyMixin.__init__(self, key_type)
       superclass.__init__(self, *a, **kw)
       if not all(map(lambda key: type(key) is key_type, self.keys())):
         raise TypeError("all keys must be of type %s" % (key_type,))

   if name is None:
     name = f'{key_type.__name__}Typed{superclass.__name__}'
   TypedKeyMapping.__name__ = name
   TypedKeyMapping.__doc__ = stripped_dedent(
       f'''
       Subclass of `{superclass.__name__}` which ensures that its
       keys are of type `{key_type.__name__}` using `TypedKeyMixin`.
       '''
   )
   return TypedKeyMapping

 StrKeyedDict = TypedKeyClass(str, dict, name='StrKeyedDict')
 UUIDKeyedDict = TypedKeyClass(UUID, dict, name='UUIDKeyedDict')

The basic deal is to write a function which defines a class which uses
the function parameter values in its definition.

The above defines the factory function, and then makes two convenience
classes using the factory.

So we make a local class named TypedKeyMapping. Then there’s a bit of
boilerplate to set its name (there’s an automatic default) and its
docstring, then we return it.

Cheers,
Cameron Simpson cs@cskk.id.au

Sorry, I can’t read Perl well enough to understand what your code does :frowning:

Could you maybe describe it in pseudo-code or English?

Does the subclass already exist, or do you need to create it on the fly?

class Parrot: pass
class RedParrot(Parrot): pass

def factory(colour):
    if colour == 'red':
        # Subclass already exists.
        return RedParrot()
    elif colour == 'blue:
        # Create subclass on the fly. (Warning: this is
        # wasteful of memory and may be confusing.)
        class BlueParrot(Parrot):
            pass
        return BlueParrot()
    else:
        return Parrot()

Otherwise I’m not sure I understand your question.