class_docstr: Composable cycles.
  
  This class has compositions methods:
  
  ``+``
    for 'inner' products (zip)
  
  ``+=``
    in-place ``+``
  
  ``*``
    for outer products (`itertools.product`) and integer multiplication
  
  ``*=``
    in-place ``*``
  
  and supports basic slicing via ``[]``.
  
  Parameters
  ----------
  left, right : Cycler or None
      The 'left' and 'right' cyclers.
  op : func or None
      Function which composes the 'left' and 'right' cyclers.
docstr: Semi-private init.
  
  Do not use this directly, use `cycler` function instead.
code: def __init__(
      self,
      left: Cycler[K, V] | Iterable[dict[K, V]] | None,
      right: Cycler[K, V] | None = None,
      op: Any = None,
  ):
      """
      Semi-private init.
  
      Do not use this directly, use `cycler` function instead.
      """
      if isinstance(left, Cycler):
          self._left: Cycler[K, V] | list[dict[K, V]] = Cycler(
              left._left, left._right, left._op
          )
      elif left is not None:
          # Need to copy the dictionary or else that will be a residual
          # mutable that could lead to strange errors
          self._left = [copy.copy(v) for v in left]
      else:
          self._left = []
  
      if isinstance(right, Cycler):
          self._right: Cycler[K, V] | None = Cycler(
              right._left, right._right, right._op
          )
      else:
          self._right = None
  
      self._keys: set[K] = _process_keys(self._left, self._right)
      self._op: Any = op
  
imports: from __future__ import annotations
  from collections.abc import Hashable, Iterable, Generator
  import copy
  from functools import reduce
  from itertools import product, cycle
  from operator import mul, add
  from typing import TypeVar, Generic, Callable, Union, Dict, List, Any, overload, cast
label_desc: Use image node_id 2 to create a new Cycler object from inherited base classes: Generic with example: obj = Cycler(left, right, op)