class_docstr: Operation-specific methods and properties for the :class:`~.ops.op_math.Controlled` class.
  
  When an :class:`~.operation.Operation` is provided to the :class:`~.ops.op_math.Controlled`
  class, this type is constructed instead. It adds some additional :class:`~.operation.Operation`
  specific methods and properties.
  
  When we no longer rely on certain functionality through ``Operation``, we can get rid of this
  class.
  
  .. seealso:: :class:`~.Controlled`
code: def __init__(
      self,
      base,
      control_wires,
      control_values=None,
      work_wires=None,
      id=None,
  ):
      super().__init__(
          base, control_wires, control_values, work_wires, id
      )
      # check the grad_recipe validity
      if self.grad_recipe is None:
          # Make sure grad_recipe is an iterable of correct length instead of None
          self.grad_recipe = [None] * self.num_params
  
imports: import warnings
  from copy import copy
  from functools import wraps
  from inspect import signature
  from typing import List
  import numpy
  from scipy import sparse
  import pennylane
  from pennylane import operation
  from pennylane import math
  from pennylane.operation import Operator
  from pennylane.wires import Wires
  from pennylane.compiler import compiler
  from .symbolicop import SymbolicOp
  from .controlled_decompositions import ctrl_decomp_bisect, ctrl_decomp_zyz
label_desc: Use image node_id 2 to create a new ControlledOp object from inherited base classes: Controlled, operation with example: obj = ControlledOp(base, control_wires, control_values, work_wires, id)