code: def random_product(items, num=None, rng=None):
      import utool as ut
      rng = ut.ensure_rng(rng, 'python')
      seen = set()
      items = [list(g) for g in items]
      max_num = ut.prod(map(len, items))
      if num is None:
          num = max_num
      if num > max_num:
          raise ValueError('num exceedes maximum number of products')
      if num > max_num // 2:
          for prod in ut.shuffle(list(it.product(*items)), rng=rng):
              yield prod
      else:
          while len(seen) < num:
              idxs = tuple(rng.randint(0, len(g) - 1) for g in items)
              if idxs not in seen:
                  seen.add(idxs)
                  prod = tuple(g[x] for g, x in zip(items, idxs))
                  yield prod