class_docstr: 定制给 :class:`~fastNLP.core.dataloaders.MixDataLoader` 的 ``BatchSampler``，其功能是将传入的 ``datasets`` 轮流采样并返回 index，
  处理结束上个 dataset 的一个 batch 后会处理下一个。
class_docstr_tok: ["\u5b9a\u5236\u7ed9",":","class",":","`","~fastNLP.core.dataloaders.MixDataLoader","`","\u7684","``","BatchSampler","``","\uff0c\u5176\u529f\u80fd\u662f\u5c06\u4f20\u5165\u7684","``","datasets","``","\u8f6e\u6d41\u91c7\u6837\u5e76\u8fd4\u56de","index\uff0c","\u5904\u7406\u7ed3\u675f\u4e0a\u4e2a","dataset","\u7684\u4e00\u4e2a","batch","\u540e\u4f1a\u5904\u7406\u4e0b\u4e00\u4e2a\u3002"]
code: def __iter__(self) -> List[int]:
      # sampler为str， 此时为单机多卡或者单机，可以实现rand随机化
      if isinstance(self.sampler, str):
          if self.sampler == "seq":
              self.sampler = {}
              for name, per_ds in self.datasets.items():
                  if self.word_size >= 0 and self.rank >= 0:
                      self.sampler[name] = InnerSampler(
                          list(range(len(per_ds)))[
                              self.rank :: self.word_size
                          ]
                      )
                  else:
                      self.sampler[name] = InnerSampler(
                          list(range(len(per_ds)))
                      )
          elif self.sampler == "rand":
              self.sampler = {}
              for name, per_ds in self.datasets.items():
                  g = torch.Generator()
                  g.manual_seed(self.epoch)
                  indices = torch.randperm(
                      len(per_ds), generator=g
                  ).tolist()
                  if self.word_size >= 0 and self.rank >= 0:
                      self.sampler[name] = InnerSampler(
                          indices[self.rank :: self.word_size]
                      )
                  else:
                      self.sampler[name] = InnerSampler(indices)
  
          # 根据给定的ds_ratio计算真正需要处理数据集
          if isinstance(self.sampler, Dict):
              if self.ds_ratio is None:
                  sampler_lens = [
                      len(spl) for _, spl in self.sampler.items()
                  ]
  
              elif self.ds_ratio == "pad_to_most":
                  sampler_len = sum([1 for _ in self.sampler.keys()])
                  sampler_lens = [
                      max(len(spl) for _, spl in self.sampler.items())
                  ] * sampler_len
  
              elif self.ds_ratio == "truncate_to_least":
                  sampler_len = sum([1 for _ in self.sampler.keys()])
                  sampler_lens = [
                      min(len(spl) for _, spl in self.sampler.items())
                  ] * sampler_len
  
              elif isinstance(self.ds_ratio, Dict):
                  if not all(item >= 0 for item in self.ds_ratio):
                      raise ValueError(
                          "batch_size should be a positive integer value, "
                          "but got ds_ratio={}".format(self.ds_ratio)
                      )
                  sampler_lens = [
                      int(len(spl) * self.ds_ratio[name])
                      for name, spl in self.sampler.items()
                  ]
              else:
                  raise ValueError(
                      f"{self.ds_ratio} must be pad_to_least or truncate_to_least or None or List"
                  )
              total_lens = sum(sampler_lens)
          else:
              raise ValueError("datasets must be dict or list")
          # 初始化参数
          sampler_index = [sampler_lens[0]]
          for idx in sampler_lens[1:]:
              temp = sampler_index[-1]
              sampler_index.append(temp + idx)
          self.num_samplers = sampler_index
          self.len_samplers = total_lens
  
      start_idx, samplers, true_start_idx, true_end_idx = 0, [], 0, 0
  
      # （特定数据集需要长度，特定数据集sampler, 特定数据集的基址， 特定sampler的下标）
      for idx, (name, spl) in enumerate(self.sampler.items()):
          end_idx = len(spl)
          true_end_idx = self.num_samplers[idx]
          samplers.append(
              (
                  iter(range(true_start_idx, true_end_idx)),
                  iter(spl),
                  start_idx,
                  name,
              )
          )
          start_idx += end_idx
          true_start_idx = true_end_idx
  
      while True:
          # 退出循环
          if len(samplers) == 0:
              break
          batch_idx, flag = [], False
          (
              ds_total_iter,
              ds_sampler,
              ds_base_idx,
              sampler_idx,
          ) = samplers.pop(0)
          for _ in range(self.batch_size):
              try:
                  # 取出数据
                  next(ds_total_iter)
                  # 取出真正数据， 若取完则重新初始化一个
                  try:
                      batch_idx.append(next(ds_sampler) + ds_base_idx)
                  except StopIteration:
                      ds_sampler = iter(self.sampler[sampler_idx])
                      batch_idx.append(next(ds_sampler) + ds_base_idx)
              except StopIteration:
                  # 当前ds所有的数据集采样完毕，将其清除队列
                  flag = True
          # 判断是否真正解决某个数据集的采样
          if flag is False:
              samplers.append(
                  (ds_total_iter, ds_sampler, ds_base_idx, sampler_idx)
              )
          if len(batch_idx) == self.batch_size:
              yield batch_idx
          elif len(batch_idx) > 0 and not self.drop_last:
              yield batch_idx
  
imports: import array
  import numpy
  from typing import Union, List, Iterable, Dict
  from fastNLP.envs.imports import _NEED_IMPORT_TORCH
label_desc: Use image node_id 2 for calling the PollingSampler obj's underlying member method code with example usage: obj.__iter__() without return types