class_docstr: Base class for numpy operators. numpy operators allow parts
  of computation in symbolic graph to be writen in numpy. This feature
  is intended for quickly hacking out a solution for non performance
  critical parts. Please consider write a c++ implementation if it becomes
  a bottleneck.
  Note that if your operator contains internal states (like arrays),
  it cannot be used for multi-gpu training.
class_docstr_tok: ["Base","class","for","numpy","operators",".","numpy","operators","allow","parts","of","computation","in","symbolic","graph","to","be","writen","in","numpy",".","This","feature","is","intended","for","quickly","hacking","out","a","solution","for","non","performance","critical","parts",".","Please","consider","write","a","c++","implementation","if","it","becomes","a","bottleneck",".","Note","that","if","your","operator","contains","internal","states","(","like","arrays",")",",","it","can","not","be","used","for","multi-gpu","training","."]
code: def get_symbol(self, *args, **kwargs):
      fb_functype = CFUNCTYPE(
          c_bool, c_int, POINTER(c_void_p), POINTER(c_int), c_void_p
      )
      infer_functype = CFUNCTYPE(
          c_bool,
          c_int,
          POINTER(c_int),
          POINTER(POINTER(mx_int)),
          c_void_p,
      )
      list_functype = CFUNCTYPE(
          c_bool, POINTER(POINTER(POINTER(c_char))), c_void_p
      )
      deps_functype = CFUNCTYPE(
          c_bool,
          c_int_p,
          c_int_p,
          c_int_p,
          c_int_p,
          POINTER(c_int_p),
          c_void_p,
      )
  
      class NDArrayOpInfo(Structure):
          """Structure that holds Callback information. Passed to NDArrayOpProp"""
  
          _fields_ = [
              ("forward", fb_functype),
              ("backward", fb_functype),
              ("infer_shape", infer_functype),
              ("list_outputs", list_functype),
              ("list_arguments", list_functype),
              ("declare_backward_dependency", deps_functype),
              ("p_forward", c_void_p),
              ("p_backward", c_void_p),
              ("p_infer_shape", c_void_p),
              ("p_list_outputs", c_void_p),
              ("p_list_arguments", c_void_p),
              ("p_declare_backward_dependency", c_void_p),
          ]
  
      def forward_entry(num_ndarray, ndarraies, tags, _):
          """C Callback for NDArrayOp::Forward"""
          try:
              tensors = [[] for i in range(4)]
              for i in range(num_ndarray):
                  if tags[i] == 1:
                      tensors[tags[i]].append(
                          NDArray(
                              cast(ndarraies[i], NDArrayHandle),
                              writable=True,
                          )
                      )
                  else:
                      tensors[tags[i]].append(
                          NDArray(
                              cast(ndarraies[i], NDArrayHandle),
                              writable=False,
                          )
                      )
              self.forward(in_data=tensors[0], out_data=tensors[1])
          except Exception:
              print(
                  f"Error in NDArrayOp.forward: {traceback.format_exc()}"
              )
              return False
          return True
  
      def backward_entry(num_ndarray, ndarraies, tags, _):
          """C Callback for NDArrayOp::Backward"""
          try:
              tensors = [[] for i in range(4)]
              for i in range(num_ndarray):
                  if tags[i] == 2:
                      tensors[tags[i]].append(
                          NDArray(
                              cast(ndarraies[i], NDArrayHandle),
                              writable=True,
                          )
                      )
                  else:
                      tensors[tags[i]].append(
                          NDArray(
                              cast(ndarraies[i], NDArrayHandle),
                              writable=False,
                          )
                      )
              self.backward(
                  in_data=tensors[0],
                  out_data=tensors[1],
                  in_grad=tensors[2],
                  out_grad=tensors[3],
              )
          except Exception:
              print(
                  f"Error in NDArrayOp.backward: {traceback.format_exc()}"
              )
              return False
          return True
  
      def infer_shape_entry(num_tensor, tensor_dims, tensor_shapes, _):
          """C Callback for NDArrayOpProp::InferShape"""
          try:
              n_in = len(self.list_arguments())
              n_out = len(self.list_outputs())
              assert num_tensor == n_in + n_out
  
              shapes = [
                  [tensor_shapes[i][j] for j in range(tensor_dims[i])]
                  for i in range(n_in)
              ]
              ishape, oshape = self.infer_shape(shapes)
              assert len(oshape) == n_out
              assert len(ishape) == n_in
              rshape = list(ishape) + list(oshape)
              for i in range(n_in + n_out):
                  tensor_shapes[i] = cast(
                      c_array_buf(mx_int, array("i", rshape[i])),
                      POINTER(mx_int),
                  )
                  tensor_dims[i] = len(rshape[i])
          except Exception:
              print(
                  f"Error in NDArrayOp.infer_shape: {traceback.format_exc()}"
              )
              return False
          return True
  
      def list_outputs_entry(out, _):
          """C Callback for NDArrayOpProp::ListOutputs"""
          try:
              ret = self.list_outputs()
              ret = [c_str(i) for i in ret] + [c_char_p(0)]
              ret = c_array(c_char_p, ret)
              out[0] = cast(ret, POINTER(POINTER(c_char)))
          except Exception:
              print(
                  f"Error in NDArrayOp.list_outputs: {traceback.format_exc()}"
              )
              return False
          return True
  
      def list_arguments_entry(out, _):
          """C Callback for NDArrayOpProp::ListArguments"""
          try:
              ret = self.list_arguments()
              ret = [c_str(i) for i in ret] + [c_char_p(0)]
              ret = c_array(c_char_p, ret)
              out[0] = cast(ret, POINTER(POINTER(c_char)))
          except Exception:
              print(
                  f"Error in NDArrayOp.list_arguments: {traceback.format_exc()}"
              )
              return False
          return True
  
      def declare_backward_dependency(
          out_grad, in_data, out_data, num_dep, deps, _
      ):
          """C Callback for NDArrayOpProp::DeclareBacwardDependency"""
          try:
              out_grad = [
                  out_grad[i] for i in range(len(self.list_outputs()))
              ]
              in_data = [
                  in_data[i] for i in range(len(self.list_arguments()))
              ]
              out_data = [
                  out_data[i] for i in range(len(self.list_outputs()))
              ]
              rdeps = self.declare_backward_dependency(
                  out_grad, in_data, out_data
              )
              num_dep[0] = len(rdeps)
              rdeps = cast(
                  c_array_buf(c_int, array("i", rdeps)), c_int_p
              )
              deps[0] = rdeps
          except Exception:
              print(
                  f"Error in NDArrayOp.declare_backward_dependency: {traceback.format_exc()}"
              )
              return False
          return True
  
      self.info_ = NDArrayOpInfo(
          fb_functype(forward_entry),
          fb_functype(backward_entry),
          infer_functype(infer_shape_entry),
          list_functype(list_outputs_entry),
          list_functype(list_arguments_entry),
          deps_functype(declare_backward_dependency),
          None,
          None,
          None,
          None,
          None,
          None,
      )
      cb_ptr = format(cast(pointer(self.info_), c_void_p).value, "x")
      # pylint: disable=E1101
      sym = symbol._internal._NDArray(*args, info=cb_ptr, **kwargs)
      # keep a reference of ourself in PythonOp so we don't get garbage collected.
      PythonOp._ref_holder.append(self)
      return sym
  
imports: import traceback
  import warnings
  import collections
  from array import array
  from threading import Lock
  import ctypes
  from ctypes import CFUNCTYPE, POINTER, Structure, pointer
  from ctypes import c_void_p, c_int, c_char, c_char_p, cast, c_bool
  from .base import _LIB, check_call, MXCallbackList, c_array, c_array_buf, mx_int, OpHandle
  from .base import c_str, mx_uint, mx_float, ctypes2numpy_shared, NDArrayHandle, py_str
  from .None import symbol, context
  from .ndarray import NDArray, dtype_np_to_mx, dtype_mx_to_np
  from .ndarray.ndarray import _STORAGE_TYPE_STR_TO_ID, _STORAGE_TYPE_ID_TO_STR
  from .ndarray.ndarray import _STORAGE_TYPE_UNDEFINED, _STORAGE_TYPE_DEFAULT
  from .ndarray.ndarray import _STORAGE_TYPE_CSR, _STORAGE_TYPE_ROW_SPARSE
  from .ndarray import _ndarray_cls
  from .numpy.multiarray import _np_ndarray_cls
  from .util import is_np_array
label_desc: Use image node_id 2 for calling the NDArrayOp obj's underlying member method code with example usage: obj.get_symbol() and returns: sym, True, True, True, True, True, True, False, False, False, False, False, False