def to_gufunc_string(self, exclude_dims=frozenset()):
        """Create an equivalent signature string for a NumPy gufunc.

        Unlike __str__, handles dimensions that don't map to Python
        identifiers.

        Also creates unique names for input_core_dims contained in exclude_dims.
        """
        input_core_dims = [
            [self.dims_map[dim] for dim in core_dims]
            for core_dims in self.input_core_dims
        ]
        output_core_dims = [
            [self.dims_map[dim] for dim in core_dims]
            for core_dims in self.output_core_dims
        ]

        # enumerate input_core_dims contained in exclude_dims to make them unique
        if exclude_dims:
            exclude_dims = [self.dims_map[dim] for dim in exclude_dims]

            counter: Counter = Counter()

            def _enumerate(dim):
                if dim in exclude_dims:
                    n = counter[dim]
                    counter.update([dim])
                    dim = f"{dim}_{n}"
                return dim

            input_core_dims = [
                [_enumerate(dim) for dim in arg] for arg in input_core_dims
            ]

        alt_signature = type(self)(input_core_dims, output_core_dims)
        return str(alt_signature)
Create an equivalent signature string for a NumPy gufunc.

        Unlike __str__, handles dimensions that don't map to Python
        identifiers.

        Also creates unique names for input_core_dims contained in exclude_dims.
        
xarray/computation/apply_ufunc.py