code: def cartesian_product(X):
      
      msg = "Input must be a list-like of list-likes"
      if not is_list_like(X):
          raise TypeError(msg)
      for x in X:
          if not is_list_like(x):
              raise TypeError(msg)
  
      if len(X) == 0:
          return []
  
      lenX = np.fromiter((len(x) for x in X), dtype=np.intp)
      cumprodX = np.cumproduct(lenX)
  
      a = np.roll(cumprodX, 1)
      a[0] = 1
  
      if cumprodX[-1] != 0:
          b = cumprodX[-1] / cumprodX
      else:
          # if any factor is empty, the cartesian product is empty
          b = np.zeros_like(cumprodX)
  
      return [np.tile(np.repeat(np.asarray(com.values_from_object(x)), b[i]),
                      np.product(a[i]))
              for i, x in enumerate(X)]
docs: Numpy version of itertools.product.
      Sometimes faster (for large inputs)...
  
      Parameters
      ----------
      X : list-like of list-likes
  
      Returns
      -------
      product : list of ndarrays
  
      Examples
      --------
      >>> cartesian_product([list('ABC'), [1, 2]])
      [array(['A', 'A', 'B', 'B', 'C', 'C'], dtype='|S1'),
      array([1, 2, 1, 2, 1, 2])]
  
      See Also
      --------
      itertools.product : Cartesian product of input iterables.  Equivalent to
          nested for-loops.