class_docstr: DataHandler with **(L)earnable (P)rocessor**
  
  This handler will produce three pieces of data in pd.DataFrame format.
  
  - DK_R / self._data: the raw data loaded from the loader
  - DK_I / self._infer: the data processed for inference
  - DK_L / self._learn: the data processed for learning model.
  
  The motivation of using different processor workflows for learning and inference
  Here are some examples.
  
  - The instrument universe for learning and inference may be different.
  - The processing of some samples may rely on label (for example, some samples hit the limit may need extra processing or be dropped).
  
      - These processors only apply to the learning phase.
  
  Tips for data handler
  
  - To reduce the memory cost
  
      - `drop_raw=True`: this will modify the data inplace on raw data;
  
  - Please note processed data like `self._infer` or `self._learn` are concepts different from `segments` in Qlib's `Dataset` like "train" and "test"
  
      - Processed data like `self._infer` or `self._learn` are underlying data processed with different processors
      - `segments` in Qlib's `Dataset` like "train" and "test" are simply the time segmentations when querying data("train" are often before "test" in time-series).
      - For example, you can query `data._infer` processed by `infer_processors` in the "train" time segmentation.
docstr: Parameters
  ----------
  infer_processors : list
      - list of <description info> of processors to generate data for inference
  
      - example of <description info>:
  
      .. code-block::
  
          1) classname & kwargs:
              {
                  "class": "MinMaxNorm",
                  "kwargs": {
                      "fit_start_time": "20080101",
                      "fit_end_time": "20121231"
                  }
              }
          2) Only classname:
              "DropnaFeature"
          3) object instance of Processor
  
  learn_processors : list
      similar to infer_processors, but for generating data for learning models
  
  process_type: str
      PTYPE_I = 'independent'
  
      - self._infer will be processed by infer_processors
  
      - self._learn will be processed by learn_processors
  
      PTYPE_A = 'append'
  
      - self._infer will be processed by infer_processors
  
      - self._learn will be processed by infer_processors + learn_processors
  
        - (e.g. self._infer processed by learn_processors )
  drop_raw: bool
      Whether to drop the raw data
code: def __init__(
      self,
      instruments=None,
      start_time=None,
      end_time=None,
      data_loader: Union[dict, str, DataLoader] = None,
      infer_processors: List = [],
      learn_processors: List = [],
      shared_processors: List = [],
      process_type=PTYPE_A,
      drop_raw=False,
      **kwargs,
  ):
      """
      Parameters
      ----------
      infer_processors : list
          - list of <description info> of processors to generate data for inference
  
          - example of <description info>:
  
          .. code-block::
  
              1) classname & kwargs:
                  {
                      "class": "MinMaxNorm",
                      "kwargs": {
                          "fit_start_time": "20080101",
                          "fit_end_time": "20121231"
                      }
                  }
              2) Only classname:
                  "DropnaFeature"
              3) object instance of Processor
  
      learn_processors : list
          similar to infer_processors, but for generating data for learning models
  
      process_type: str
          PTYPE_I = 'independent'
  
          - self._infer will be processed by infer_processors
  
          - self._learn will be processed by learn_processors
  
          PTYPE_A = 'append'
  
          - self._infer will be processed by infer_processors
  
          - self._learn will be processed by infer_processors + learn_processors
  
            - (e.g. self._infer processed by learn_processors )
      drop_raw: bool
          Whether to drop the raw data
      """
  
      # Setup preprocessor
      self.infer_processors = []  # for lint
      self.learn_processors = []  # for lint
      self.shared_processors = []  # for lint
      for pname in (
          "infer_processors",
          "learn_processors",
          "shared_processors",
      ):
          for proc in locals()[pname]:
              getattr(self, pname).append(
                  init_instance_by_config(
                      proc,
                      None
                      if (
                          isinstance(proc, dict)
                          and "module_path" in proc
                      )
                      else processor_module,
                      accept_types=processor_module.Processor,
                  )
              )
  
      self.process_type = process_type
      self.drop_raw = drop_raw
      super().__init__(
          instruments, start_time, end_time, data_loader, **kwargs
      )
  
imports: import warnings
  from typing import Callable, Union, Tuple, List, Iterator, Optional
  import pandas
  from qlib.typehint import Literal
  from ...log import get_module_logger, TimeInspector
  from ...utils import init_instance_by_config
  from ...utils.serial import Serializable
  from .utils import fetch_df_by_index, fetch_df_by_col
  from ...utils import lazy_sort_index
  from .loader import DataLoader
  from .None import processor
  from .None import loader
label_desc: Use image node_id 1 to create a new DataHandlerLP object from inherited base classes: DataHandler with example: obj = DataHandlerLP(instruments, start_time, end_time, data_loader, infer_processors, learn_processors, shared_processors, process_type, drop_raw)