How can I control the number of sub-panel instances from an IntProperty?
Dynamically register with python type
Can create a class using the type method.  Code below makes a class name, makes a class with that name and sets the bl_idname class attribute to it as well.  Note can pass draw methods et all in dictionary.
    id = f&quot;OBJECTTOOL_PT_subx{n}&quot;
    panel = type(id,
        (OBJECTTOOL_PT_sub_panel, Panel, ),
        {&quot;bl_idname&quot; : id}
        )    

Hence with a dynamic update on int property can register or unregister a subpanel classes on the fly.  Used to be my go to method. It has since been my experience that quick scrubbing of a property can befuddle the registering and unregistering internals and start to fail and report missing RNA errors.
Getting the value of the scene property during restricted context when addons register is an issue if dynamically registering on fly with an update method.
Polling on the number

Instead for multi subpanels these days I go for a register them all (or in chunks as need be) approach and use a class property to poll against.  The parent class poll will take care of any outside polling needs.
Add a class attribute number to each on creations, register them all and poll based on the number.
Another bonus is if the file is saved with 4 as the count prop, it will show 4 panels (when next run)
import bpy
from bpy.types import Operator, Panel, PropertyGroup, Menu
from bpy.props import IntProperty, PointerProperty
from bpy.utils import register_class, unregister_class


class OBJECTTOOL_PT_main_panel(Panel):
    bl_label = &quot;Object Tools&quot;
    bl_idname = &quot;OBJECTTOOL_PT_main_panel&quot;
    bl_space_type = &quot;VIEW_3D&quot;   
    bl_region_type = &quot;UI&quot;
    bl_category = &quot;Object Tools&quot;
    bl_context = &quot;objectmode&quot;

    def draw(self, context):
        layout = self.layout
        scene = context.scene
        objecttools = scene.objecttools
        row = layout.row()
        row.prop(objecttools, &quot;count&quot;)

class OBJECTTOOL_PT_sub_panel(Panel):
    bl_label = &quot;Sub Panel&quot;
    bl_idname = &quot;OBJECTTOOL_PT_sub_panel&quot;
    bl_space_type = &quot;VIEW_3D&quot;   
    bl_region_type = &quot;UI&quot;
    bl_category = &quot;Object Tools&quot;
    bl_context = &quot;objectmode&quot;
    bl_parent_id = &quot;OBJECTTOOL_PT_main_panel&quot;

    @classmethod
    def poll(cls, context):
        ot = context.scene.objecttools
        return cls.count &lt; ot.count

    def draw(self, context):
        layout = self.layout
        layout.label(text=&quot;SUBBY&quot;)

    
class OBJECTTOOL_Settings(PropertyGroup):

    count: IntProperty(
        name = &quot;Count&quot;,
        description=&quot;Number of objects to create&quot;,
        default = 1,
        min = 1,
        max = 6,
        )        


classes = [
    OBJECTTOOL_Settings,
    OBJECTTOOL_PT_main_panel,
]

for i in range(5):
    id = f&quot;OBJECTTOOL_PT_subx{i}&quot;
    panel = type(id,
        (OBJECTTOOL_PT_sub_panel, Panel, ),
        {&quot;bl_idname&quot; : id,
         &quot;count&quot; : i}
        )
    classes.append(panel)

def register():
    from bpy.utils import register_class
    for cls in classes:
        register_class(cls)

    bpy.types.Scene.objecttools = PointerProperty(type=OBJECTTOOL_Settings)

def unregister():
    from bpy.utils import unregister_class
    for cls in reversed(classes):
        unregister_class(cls)
    del bpy.types.Scene.objecttools


if __name__ == &quot;__main__&quot;:
    register()

Related
https://blender.stackexchange.com/a/179031/15543
https://blender.stackexchange.com/a/135374/15543