code: def replace_batch_sampler(
      dataloader: "DataLoader", batch_sampler: "BatchSampler"
  ):
      """
      利用 ``batch_sampler`` 重新构建一个 ``DataLoader``，起到替换 ``batch_sampler`` 又不影响原 ``dataloader`` 的作用。
      考虑了用户自己定制了 ``DataLoader`` 的情形。
      """
      # 拿到非下划线开头的实例属性；
      instance_attrs = {
          k: v
          for k, v in vars(dataloader).items()
          if not k.startswith("_")
      }
  
      # 拿到 dataloader '__init__' 函数的默认函数签名；可以获取参数名和参数的默认值以及类型
      init_params = dict(
          inspect.signature(dataloader.__init__).parameters
      )
  
      # 这里为什么要单独弄的原因在于，用户在定制自己的 dataloader 的同时可能为了方便只设定一些参数，而后面直接使用 **kwargs 的方式，这时如果
      # 其在初始化自己的 dataloader 实例的时候加入了一些其它的新的参数（首先这一步是必要的，因为我们只能通过这样加 sampler；另一方面，用户
      # 可能确实通过 **kwargs 加入了一些新的参数），如果假设用户是这样使用的： "super().__init__(**kwargs)"，那么我们就只能去 DataLoader
      # 中寻找；VAR_KEYWORD 代表 **kwargs
      has_variadic_kwargs = any(
          v.kind is v.VAR_KEYWORD for k, v in init_params.items()
      )
      if has_variadic_kwargs:
          for key, value in dict(
              inspect.signature(DataLoader.__init__).parameters
          ).items():
              if key not in init_params and key != "self":
                  init_params[key] = value
  
      # 如果初始化dataloader所使用的参数不是默认值，那么我们需要将其记录下来用于重新初始化时设置；
      non_default_params = {
          name
          for name, p in init_params.items()
          if name in instance_attrs
          and p.default != instance_attrs[name]
      }
      # add `dataset` as it might have been replaced with `*args`
      non_default_params.add("dataset")
  
      reconstruct_args = {
          k: v
          for k, v in instance_attrs.items()
          if k in non_default_params
      }
      if isinstance(dataloader, DataLoader):
          reconstruct_args.update(
              {
                  "batch_sampler": batch_sampler,
                  "shuffle": False,
                  "drop_last": False,
                  "batch_size": 1,
                  "persistent_workers": dataloader._persistent_workers,
              }
          )
  
      # POSITIONAL_OR_KEYWORD 代表一般的参数
      # 收集初始化函数中出现的、一般形式的、不带默认值且不在 reconstruct_args 中的参数
      # 也即它们没有在初始化函数和实例成员中同时出现
      required_args = {
          p.name
          for p in init_params.values()
          if p.kind in (p.POSITIONAL_ONLY, p.POSITIONAL_OR_KEYWORD)
          and p.default is p.empty
          and p.name not in reconstruct_args
      }
  
      # 这种错误针对的是 __init__ 中的参数没有用同样名字的 self 挂上；
      if required_args:
          required_args = sorted(required_args)
          dataloader_self_name = dataloader.__class__.__name__
          raise Exception(
              f"Need to inject arguments {required_args} into the __init__ of `{dataloader_self_name}`. "
              f"But they are not found in the attribute of `{dataloader_self_name}`, fastNLP cannot determine its "
              f"value when try to reinitialize `{dataloader_self_name}`, please add `{required_args}` to be "
              f"`{dataloader_self_name}`'s attribute."
          )
  
      # 这种错误针对的是传入的 dataloader 不是直接的 DataLoader，而是定制了 DataLoader，但是 __init__ 中没有 **kwargs；
      if not has_variadic_kwargs:
          # the dataloader signature does not allow keyword arguments that need to be passed
          missing_kwargs = reconstruct_args.keys() - init_params.keys()
          if missing_kwargs:
              missing_kwargs = sorted(missing_kwargs)
              dataloader_self_name = dataloader.__class__.__name__
              raise Exception(
                  f"The parameter:{missing_kwargs} needed to reinitialize `{dataloader_self_name}` is not found."
              )
          # 如果没有kwargs，则保证一下只传入需要的参数
          if not isinstance(dataloader, DataLoader):
              reconstruct_args = {
                  key: value
                  for key, value in reconstruct_args.items()
                  if key in init_params
              }
  
      return type(dataloader)(**reconstruct_args)
  
imports: import socket
  import os
  import struct
  import random
  import inspect
  import numpy
  from copy import deepcopy
  from contextlib import ExitStack, closing
  from typing import Dict, Optional
  from fastNLP.envs.imports import _NEED_IMPORT_PADDLE
  from fastNLP.envs.utils import get_global_seed
  from fastNLP.envs import get_global_rank, FASTNLP_BACKEND_LAUNCH, FASTNLP_GLOBAL_SEED
  from fastNLP.core.samplers import ReproducibleBatchSampler
  from fastNLP.core.utils import auto_param_call, paddle_to
  from fastNLP.core.log import logger
label_desc: Use image node_id 4 for calling a global function with example usage: replace_batch_sampler(dataloader, batch_sampler) and returns: type