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: Set up the data in case of running initialization for multiple time
  
  Parameters
  ----------
  init_type : str
      The type `IT_*` listed above.
  enable_cache : bool
      default value is false:
  
      - if `enable_cache` == True:
  
          the processed data will be saved on disk, and handler will load the cached data from the disk directly
          when we call `init` next time
code: def setup_data(self, init_type: str = IT_FIT_SEQ, **kwargs):
      """
      Set up the data in case of running initialization for multiple time
  
      Parameters
      ----------
      init_type : str
          The type `IT_*` listed above.
      enable_cache : bool
          default value is false:
  
          - if `enable_cache` == True:
  
              the processed data will be saved on disk, and handler will load the cached data from the disk directly
              when we call `init` next time
      """
      # init raw data
      super().setup_data(**kwargs)
  
      with TimeInspector.logt("fit & process data"):
          if init_type == DataHandlerLP.IT_FIT_IND:
              self.fit()
              self.process_data()
          elif init_type == DataHandlerLP.IT_LS:
              self.process_data()
          elif init_type == DataHandlerLP.IT_FIT_SEQ:
              self.fit_process_data()
          else:
              raise NotImplementedError(
                  f"This type of input is not supported"
              )
  
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 9 for calling the DataHandlerLP obj's underlying member method code with example usage: obj.setup_data(init_type) without return types