//  [python]
def _generator(self, input_list, num_modules, scale, intermediate_outputs=False, recursion_frequency=1, reuse=False):
    with tf.variable_scope('generator', reuse=reuse):
      # pre-process
      input_list = tf.cast(input_list, tf.float32)
      input_list = self._mean_shift(input_list)
      x = input_list

      # initial feature extraction
      with tf.variable_scope('first_conv'):
        x = self._conv2d(x, num_features=FLAGS.bsrn_conv_features, kernel_size=(3, 3))
      
      # initial state
      if (FLAGS.bsrn_state_features > 0):
        state = tf.zeros([tf.shape(x)[0], tf.shape(x)[1], tf.shape(x)[2], FLAGS.bsrn_state_features], tf.float32)
      else:
        state = None

      # residual modules
      x_intermediate_list = []
      for i in range(num_modules):
        with tf.variable_scope('residual_modules', reuse=(reuse or (i > 0))):
          x, state = self._residual_module(x, num_features=FLAGS.bsrn_conv_features, state=state, num_state_features=FLAGS.bsrn_state_features, num_blocks=1)
          if (intermediate_outputs):
            if ((i+1) % recursion_frequency == 0):
              x_intermediate_list.append(x)
      if (not intermediate_outputs):
        x_intermediate_list.append(x)
      
      # upscaling
      x_upscale_list = []
      for (i, x) in enumerate(x_intermediate_list):
        with tf.variable_scope('upscale', reuse=(reuse or (i > 0))):
          pred_fn_pairs = []
          if (2 in self.model_scale_list):
            pred_fn_pairs.append((tf.equal(scale, 2), lambda: self._scale_specific_upscaling(x, scale=2, num_features=FLAGS.bsrn_conv_features)))
          if (3 in self.model_scale_list):
            pred_fn_pairs.append((tf.equal(scale, 3), lambda: self._scale_specific_upscaling(x, scale=3, num_features=FLAGS.bsrn_conv_features)))
          if (4 in self.model_scale_list):
            pred_fn_pairs.append((tf.equal(scale, 4), lambda: self._scale_specific_upscaling(x, scale=4, num_features=FLAGS.bsrn_conv_features)))
          if (8 in self.model_scale_list):
            pred_fn_pairs.append((tf.equal(scale, 8), lambda: self._scale_specific_upscaling(x, scale=8, num_features=FLAGS.bsrn_conv_features)))
          x = tf.case(pred_fn_pairs, exclusive=True)
          x_upscale_list.append(x)

      
      # last feature extraction
      x_last_conv_list = []
      for (i, x) in enumerate(x_upscale_list):
        with tf.variable_scope('last_conv', reuse=(reuse or (i > 0))):
          if (len(self.model_scale_list) > 1):
            def _last_conv(x, scale):
              with tf.variable_scope('x%d' % (scale)):
                x = self._conv2d(x, num_features=3, kernel_size=(3, 3))
              return x

            pred_fn_pairs = []
            if (2 in self.model_scale_list):
              pred_fn_pairs.append((tf.equal(scale, 2), lambda: _last_conv(x, scale=2)))
            if (3 in self.model_scale_list):
              pred_fn_pairs.append((tf.equal(scale, 3), lambda: _last_conv(x, scale=3)))
            if (4 in self.model_scale_list):
              pred_fn_pairs.append((tf.equal(scale, 4), lambda: _last_conv(x, scale=4)))
            if (8 in self.model_scale_list):
              pred_fn_pairs.append((tf.equal(scale, 8), lambda: _last_conv(x, scale=8)))
            x = tf.case(pred_fn_pairs, exclusive=True)
          else:
            x = self._conv2d(x, num_features=3, kernel_size=(3, 3))
          x_last_conv_list.append(x)
      
      # post-process
      output_list = []
      for (i, x) in enumerate(x_last_conv_list):
        x_final = self._mean_inverse_shift(x)
        output_list.append(x_final)
    
    if (not intermediate_outputs):
      output_list = output_list[-1]
    
    return output_list