user: Describe Integration through Classes from the Blender manual or Python API, including usage steps and snippets.

assistant: Running Python scripts in the text editor is useful for testing but you’ll
want to extend Blender to make tools accessible like other built-in functionality.

The Blender Python API allows integration for:

- [`bpy.types.Panel`](bpy.types.Panel.html#bpy.types.Panel "bpy.types.Panel")
- [`bpy.types.Menu`](bpy.types.Menu.html#bpy.types.Menu "bpy.types.Menu")
- [`bpy.types.Operator`](bpy.types.Operator.html#bpy.types.Operator "bpy.types.Operator")
- [`bpy.types.PropertyGroup`](bpy.types.PropertyGroup.html#bpy.types.PropertyGroup "bpy.types.PropertyGroup")
- [`bpy.types.KeyingSet`](bpy.types.KeyingSet.html#bpy.types.KeyingSet "bpy.types.KeyingSet")
- [`bpy.types.RenderEngine`](bpy.types.RenderEngine.html#bpy.types.RenderEngine "bpy.types.RenderEngine")

This is intentionally limited. Currently, for more advanced features such as mesh modifiers,
object types, or shader nodes, C/C++ must be used.

For Python integration Blender defines methods which are common to all types.
This works by creating a Python subclass of a Blender class which contains variables and functions
specified by the parent class which are predefined to interface with Blender.

For example:

```
import bpy
class SimpleOperator(bpy.types.Operator):
    bl_idname = "object.simple_operator"
    bl_label = "Tool Name"

    def execute(self, context):
        print("Hello World")
        return {'FINISHED'}

bpy.utils.register_class(SimpleOperator)
```

First note that it defines a subclass as a member of [`bpy.types`](bpy.types.html#module-bpy.types "bpy.types"),
this is common for all classes which can be integrated with Blender and
is used to distinguish an Operator from a Panel when registering.

Both class properties start with a `bl_` prefix.
This is a convention used to distinguish Blender properties from those you add yourself.
Next see the execute function, which takes an instance of the operator and the current context.
A common prefix is not used for functions.
Lastly the register function is called, this takes the class and loads it into Blender. See [Class Registration](#class-registration).

Regarding inheritance, Blender doesn’t impose restrictions on the kinds of class inheritance used,
the registration checks will use attributes and functions defined in parent classes.

Class mix-in example:

```
import bpy
class BaseOperator:
    def execute(self, context):
        print("Hello World BaseClass")
        return {'FINISHED'}

class SimpleOperator(bpy.types.Operator, BaseOperator):
    bl_idname = "object.simple_operator"
    bl_label = "Tool Name"

bpy.utils.register_class(SimpleOperator)
```

So once the class is registered with Blender, instancing the class and calling the functions is left up to Blender.
In fact you cannot instance these classes from the script as you would expect with most Python API’s.
To run operators you can call them through the operator API, e.g:

```
import bpy
bpy.ops.object.simple_operator()
```

User interface classes are given a context in which to draw, buttons, window, file header, toolbar, etc.,
then they are drawn when that area is displayed so they are never called by Python scripts directly.

### Construction & Destruction

In the examples above, the classes don’t define an `__init__(self)` function.
In general, defining custom constructors or destructors should not be needed, and is not recommended.

The lifetime of class instances is usually very short (also see the
[dedicated section](info_gotchas_internal_data_and_python_objects.html#blender-py-objects-life-time)), a panel for example will
have a new instance for every redraw.
Some other types, like [`bpy.types.Operator`](bpy.types.Operator.html#bpy.types.Operator "bpy.types.Operator"), have an even more complex internal handling,
which can lead to several instantiations for a single operator execution.

There are a few cases where defining `__init__()` does make sense, e.g. when sub-classing a
[`bpy.types.RenderEngine`](bpy.types.RenderEngine.html#bpy.types.RenderEngine "bpy.types.RenderEngine"). When doing so, the parent matching function must always be called,
otherwise Blender’s internal initialization won’t happen properly:

```
import bpy
class AwesomeRaytracer(bpy.types.RenderEngine):
   def __init__(self, *args, **kwargs):
      super().__init__(*args, **kwargs)
      self.my_var = 42
      ...
```