Skip to content

Add symmetric_difference to Counter #138682

Description

@rhettinger

Proposal

This was recently proposed on discuss.python.org and was also proposed 15 years ago.

The old proposal did not move forward because:

  • There were almost no known use cases.
  • The Counter class was missing other multiset methods such as subset, superset, and equality tests.
  • No other language implementation could be found that supported this operation.
  • Math articles about multisets did not mention this operation.
  • It was a one-off request that seemed unlikely to recur.

Since that time, some of those reasons have changed:

  • We received a second request, so this is no longer a one-off.
  • Since Python 3.10, Counter has full support for all the standard multiset methods.
  • Maple subsequently added symdiff so now there is a precedent in another language.

Also looking at the discussions, the most obvious workaround (p | q) - (p & q) has the disadvantage of not working with signed inputs. A better workaround would be (p - q) | (q - p) which always gives the difference between the maximum count and the minimum count regardless of sign.

At this point, I'm inclined to complete the multiset API by adding symmetric_difference. With all the other multiset methods now being supported, there is a greater cognitive load for the method being missing than for it being present. It is easier to teach that all set operators are supported than teaching that all but one are supported.

The only downsides I can think of are:

  1. It's possible (and perhaps likely) that this method will never get used.
  2. Someone reading the code p ^ q would need to think carefully about what it does.

Linked PRs

Activity

  1. self-assigned this
    on Sep 8, 2025
  2. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Sep 8, 2025
  3. added a commit that references this issue on Sep 10, 2025
  4. added a commit that references this issue on Sep 26, 2025
  5. andersk commented on May 22, 2026

    @andersk
    Contributor

    I’m concerned about naming this operation Counter.__xor__. People expect ^ to be an associative operation, as it is for integers and sets, yet now

    >>> x = Counter(a=1)
    >>> y = Counter(a=10)
    >>> z = Counter(a=100)
    >>> (x ^ y) ^ z
    Counter({'a': 91})
    >>> x ^ (y ^ z)
    Counter({'a': 89})

    There’s a similar but different way to generalize set.__xor__ that behaves more like ^ and would be associative, namely the one that takes the bitwise XOR of each count:

    Counter({item: x[item] ^ y[item] for item in x | y if x[item] != y[item]})

    I don’t propose implementing that operation at this time. But can we consider renaming the subtraction-based operation from this PR to something other than __xor__ for Python 3.15, such as Counter.symmetric_difference or Counter.absolute_difference?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

3.15bugs and security fixesstdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions