hl037_
hl037_

Reputation: 3867

How to pass class keyword arguments with the `type()` built-in function?

The class statement takes keyword arguments for various features. For example, the __init_subclass__ function receives keyword arguments passed at the class declaration:

class A(object):
  def __init_subclass__(cls, **kwargs):
    print(f'{kwargs=}')

class B(A, my_arg=5):
  pass
kwargs={'my_arg': 5}

However, doing so prevents dynamic class creation: The type function does not seem to take the class keyword arguments. A factory function does, but may conflict with __init_subclass__ or similar when the factory must modify the class.

I would like to use the type() built-in function in its 3-arguments version to dynamically create a class. However, there seems to be no documented way to pass keyword arguments (like my_arg in the previous example).

What would be the recommended way of doing it ?

Upvotes: 4

Views: 711

Answers (1)

MisterMiyagi
MisterMiyagi

Reputation: 50076

The bare type is not the equivalent of class statements in Python3. Use types.new_class as a functional equivalent of class statements.

class B(A, my_arg=5):
  a = 12  # non-trivial class body

B = types.new_class(
    'B',
    # base classes of `class` statement
    bases=(A,),
    # keywords to the `class` statement
    kwds={'my_arg': 5},
    # the class body as a function
    exec_body=lambda body: body.update({'a': 12}),
)

Keep in mind that a class statement can always be wrapped in a function to allow a parameterised, functional class creation. This also allows to set most special attributes, e.g. the class name via __qualname__:

def make_b(my_arg, my_a, name=None):
    class Parameterized_B(A, my_arg=my_arg):
        a = my_a
        if name is not None:
            __qualname__ = name
    return Parameterized_B

B = make_b(5, 12, "B")

Upvotes: 5

Related Questions