New submission from Javier Dehesa <javi...@gmail.com>:

This comes from this SO question: https://stackoverflow.com/q/52382983/1782792

Currently, this works:

    > print({1, 2} in {frozenset({1, 2}))
    # True

This is strange because set is unhashable. Apparently, it is a case-specific 
feature implemented back in 2003 
(https://github.com/python/cpython/commit/19c2d77842290af9b5f470c1eea2a71d1f77c9fe),
 by which set objects are converted to frozensets when checking for membership 
in another set. Personally I feel this is a bit surprising and inconsistent, 
but that is not the only issue with it. In the original implementation, this 
conversion was basically free because the created frozenset used the same 
storage as the given one. In the current implementation, however 
(https://github.com/python/cpython/blob/3.7/Objects/setobject.c#L1888-L1906), a 
new frozenset object is created, copied from the previous one. It seems this 
was done for thread-safety. The problem with that is that it is significantly 
more expensive:

    s = set(range(100000))
    sf = frozenset(s)
    t = { sf }
    %timeit sf in t  # True
    >>> 31.6 ns ± 1.04 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops 
each)
    %timeit s in t  # True
    >>> 4.9 ms ± 168 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In the above case, using the conversion takes five order of magnitude more time 
than the regular check. I suppose there is a memory impact too.

I think this (as far as I know) undocumented feature does not provide a 
significant usability gain, is inconsistent with the documented behavior of set 
and gives rise to obscurely underperfoming code. Removing it would be a 
breaking change, but again, affected code would be relying on undocumented 
behavior (or even "against-documentation" behavior).

----------
components: Interpreter Core
messages: 325631
nosy: Javier Dehesa
priority: normal
severity: normal
status: open
title: Deprecate set to frozenset conversion in set.__contains__
type: behavior
versions: Python 2.7, Python 3.4, Python 3.5, Python 3.6, Python 3.7, Python 3.8

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue34719>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to