Repository: matplotlib/matplotlib
File: lib/matplotlib/axes/_axes.py (Python)

Code before:
        else:
            # Note: This is equivalent to the behavior in stackplot
            # TODO: do we want to be more restrictive and check lengths?
            colors = itertools.cycle(colors)

        kwargs_gen = _style_helpers.iterate_styles(kwargs)

        bar_width = (group_distance /
                     (num_datasets + (num_datasets - 1) * bar_spacing + group_spacing))
        bar_spacing_abs = bar_spacing * bar_width
        margin_abs = 0.5 * group_spacing * bar_width

        if labels is None:
            labels = [None] * num_datasets
        else:
            assert len(labels) == num_datasets

        # place the bars, but only use numerical positions, categorical tick labels
        # are handled separately below
        bar_containers = []
        for i, (hs, label, color) in enumerate(zip(heights, labels, colors)):
            lefts = (group_centers - 0.5 * group_distance + margin_abs
                     + i * (bar_width + bar_spacing_abs))
            if orientation == "vertical":
                bc = self.bar(lefts, hs, width=bar_width, align="edge",
                              label=label, color=color, **next(kwargs_gen))
            else:
                bc = self.barh(lefts, hs, height=bar_width, align="edge",
                               label=label, color=color, **next(kwargs_gen))
            bar_containers.append(bc)

        if tick_labels is not None:
            if orientation == "vertical":
                self.xaxis.set_ticks(group_centers, labels=tick_labels)
            else:
                self.yaxis.set_ticks(group_centers, labels=tick_labels)

        return _GroupedBarReturn(bar_containers)

    @_preprocess_data()
    def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0,
             label=None, orientation='vertical'):
        """
        Create a stem plot.

        A stem plot draws lines perpendicular to a baseline at each location
        *locs* from the baseline to *heads*, and places a marker there. For
        vertical stem plots (the default), the *locs* are *x* positions, and
        the *heads* are *y* values. For horizontal stem plots, the *locs* are
        *y* positions, and the *heads* are *x* values.


Review comment (refactor):
This pattern is not ideal. It splits the iteration. Part of the advancement is done in `for ... in ...`, part is done through the `next()`. The kwargs_gen should go into the zip.

Also: Slight concern but probably ok for now: `iterate_styles()` is a bit invasive in that it handles also the non-style kwargs. After calling `iterate_styles()` the kwargs are folded into to generator and `kwargs` should likely not be used any further. In particular this means (1) all kwarg prepocessing has to be done before `iterate_styles()`, (2) we could not have another `iterate_something()` in the future.

The alternative would be something like
```python
style_kwargs, kwargs = _style_helpers.extract_style_kwargs(kwargs)
...
for i, (hs, label, color, style_kw) in enumerate(zip(heights, labels, colors, style_kwargs)):
    ...
    bar(..., color=color, **style_kw, **kwargs)
```

where we could still decide whether we extract constant style parameters and turn them into an iterator or leave them in kwargs.



Code after:
                group_distance = 1

        _api.check_in_list(["vertical", "horizontal"], orientation=orientation)

        if colors is None:
            colors = itertools.cycle([None])
        else:
            # Note: This is equivalent to the behavior in stackplot
            # TODO: do we want to be more restrictive and check lengths?
            colors = itertools.cycle(colors)

        kwargs, style_gen = _style_helpers.style_generator(kwargs)

        bar_width = (group_distance /
                     (num_datasets + (num_datasets - 1) * bar_spacing + group_spacing))
        bar_spacing_abs = bar_spacing * bar_width
        margin_abs = 0.5 * group_spacing * bar_width

        if labels is None:
            labels = [None] * num_datasets
        else:
            assert len(labels) == num_datasets

        # place the bars, but only use numerical positions, categorical tick labels
        # are handled separately below
        bar_containers = []
        for i, (hs, label, color, styles) in enumerate(zip(heights, labels, colors,
                                                           style_gen)):
            lefts = (group_centers - 0.5 * group_distance + margin_abs
                     + i * (bar_width + bar_spacing_abs))
            if orientation == "vertical":
                bc = self.bar(lefts, hs, width=bar_width, align="edge",
                              label=label, color=color, **styles, **kwargs)
            else:
                bc = self.barh(lefts, hs, height=bar_width, align="edge",
                               label=label, color=color, **styles, **kwargs)
            bar_containers.append(bc)

        if tick_labels is not None:
            if orientation == "vertical":
                self.xaxis.set_ticks(group_centers, labels=tick_labels)
            else:
                self.yaxis.set_ticks(group_centers, labels=tick_labels)

        return _GroupedBarReturn(bar_containers)

    @_preprocess_data()
    def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0,
             label=None, orientation='vertical'):
        """
        Create a stem plot.