9

How can I dynamically create a subclass of my class and provide arguments to its __init_subclass__() method?

Example class:

class MyClass:
    def __init_subclass__(cls, my_name):
        print(f"Subclass created and my name is {my_name}")

Normally I'd implement my subclass as such:

class MySubclass(MyClass, my_name="Ellis"):
    pass

But how would I pass in my_name when dynamically creating a subclass of MyClass using a metaclass? Normally I could use type() but it doesn't have the option of providing my_name.

MyDynamicSubclass = type("MyDynamicSubclass", (MyClass,), {})
12
  • 1
    What happens if you pass the keyword arguments to type at the end of the argument list? The documentation implies that it's worth trying :) Commented Aug 18, 2020 at 17:50
  • 1
    E.g. MyDynamicSubclass = type("MyDynamicSubclass", (MyClass,), {}, my_name='Ellis') Commented Aug 18, 2020 at 17:51
  • 1
    @EllisPercival yes, I think you have to do it that way Commented Aug 18, 2020 at 17:53
  • 1
    @MadPhysicist oh! That totally worked! Commented Aug 18, 2020 at 17:54
  • 1
    @EllisPercival. Thank you for an interesting question. It's been a while since I've looked into metaclasses and class creation. Commented Aug 18, 2020 at 18:16

1 Answer 1

12

The basic documentation for type does not mention that it accepts an unlimited number of keyword-only arguments, which you would supply through the keywords in a class statement. The only place this is hinted in is in the Data Model in the section Creating the class object:

Once the class namespace has been populated by executing the class body, the class object is created by calling metaclass(name, bases, namespace, **kwds) (the additional keywords passed here are the same as those passed to __prepare__).

Normally, you would not use this feature with type exactly because of __init_subclass__:

The default implementation object.__init_subclass__ does nothing, but raises an error if it is called with any arguments.

Since you have overriden the default implementation, you can create your dynamic class as

MyDynamicSubclass = type("MyDynamicSubclass", (MyClass,), {}, my_name="Ellis")
Sign up to request clarification or add additional context in comments.

2 Comments

Great, thank you! I didn't consider that the docs might omit that information. That works perfectly :)
@EllisPercival. They don't omit it as such. They just don't emphasize it. But I agree that they could be more explicit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.