class_docstr: Stationary Stochastic Bandit environment with per-arm features.
code: def _observe(self) -> types.NestedArray:
      global_obs = np.stack(
          [
              self._global_context_sampling_fn()
              for _ in range(self._batch_size)
          ]
      )
      arm_obs = np.reshape(
          [
              self._arm_context_sampling_fn()
              for _ in range(self._batch_size * self._max_num_actions)
          ],
          (self._batch_size, self._max_num_actions, -1),
      )
      self._observation = {GLOBAL_KEY: global_obs, PER_ARM_KEY: arm_obs}
  
      if self._num_actions_fn:
          num_actions = [
              self._num_actions_fn() for _ in range(self._batch_size)
          ]
          num_actions = np.maximum(num_actions, 1)
          num_actions = np.minimum(num_actions, self._max_num_actions)
          self._observation.update({NUM_ACTIONS_KEY: num_actions})
      return self._observation
  
file_path: agents/tf_agents/bandits/environments/stationary_stochastic_per_arm_py_environment.py
imports: from typing import Callable, Optional, Sequence, Text
  import gin
  import numpy
  from tf_agents.bandits.environments import bandit_py_environment
  from tf_agents.bandits.specs import utils
  from tf_agents.specs import array_spec
  from tf_agents.typing import types
label_desc: Use image node_id 4 for calling the StationaryStochasticPerArmPyEnvironment obj's underlying member method code with example usage: obj._observe() and returns: self