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: Change a key in this cycler to a new name.
  Modification is performed in-place.
  
  Does nothing if the old key is the same as the new key.
  Raises a ValueError if the new key is already a key.
  Raises a KeyError if the old key isn't a key.
code: def change_key(self, old: K, new: K) -> None:
      """
      Change a key in this cycler to a new name.
      Modification is performed in-place.
  
      Does nothing if the old key is the same as the new key.
      Raises a ValueError if the new key is already a key.
      Raises a KeyError if the old key isn't a key.
      """
      if old == new:
          return
      if new in self._keys:
          raise ValueError(
              f"Can't replace {old} with {new}, {new} is already a key"
          )
      if old not in self._keys:
          raise KeyError(
              f"Can't replace {old} with {new}, {old} is not a key"
          )
  
      self._keys.remove(old)
      self._keys.add(new)
  
      if self._right is not None and old in self._right.keys:
          self._right.change_key(old, new)
  
      # self._left should always be non-None
      # if self._keys is non-empty.
      elif isinstance(self._left, Cycler):
          self._left.change_key(old, new)
      else:
          # It should be completely safe at this point to
          # assume that the old key can be found in each
          # iteration.
          self._left = [{new: entry[old]} for entry in self._left]
  
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 5 for calling the Cycler obj's underlying member method code with example usage: obj.change_key(old, new) without return types