This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: set.discard should return True or False based on if element existed.
Type: enhancement Stage: resolved
Components: Interpreter Core Versions: Python 3.8
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: rhettinger Nosy List: Windson Yang, rhettinger, serhiy.storchaka, tzickel
Priority: normal Keywords:

Created on 2018-10-30 18:50 by tzickel, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (5)
msg328938 - (view) Author: (tzickel) * Date: 2018-10-30 18:50
Sometimes you want to do something based on if the item existed before removal, so instead of checking if it exists, then removing and doing something, if would be nice to make the function return True or False based on if the element existed.
msg328939 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-10-30 19:46
try:
    s.remove(x)
except KeyError:
    # did not exist
else:
    # existed

But catching exception in Python is expensive.
msg328964 - (view) Author: Windson Yang (Windson Yang) * Date: 2018-10-31 03:52
I guess we can implement using ref_count? However, I agreed 

"The use of variables that haven't been defined or set (implicitly or explicitly) is almost always a bad thing in any language since it indicates that the logic of the program hasn't been thought through properly, and is likely to result in unpredictable behavior."

from https://stackoverflow.com/questions/843277/how-do-i-check-if-a-variable-exists
msg328972 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2018-10-31 06:51
We already have ways to do it (use the in-operator to test membership or put a remove() call in a try/except).  Since already we have ways to do it and since those patterns are rare in practice, an API extension doesn't seem warranted.

Also, I don't really like the proposed API.  Except for methods like pop() that must return a value while mutating the data structure, it is rare in Python for mutating methods to return a value instead of None.  Another related issue is that it atypical and arguably non-pythonic to hide a mutation in a conditional, so it would lead to leas readable code.  To my eyes, in the example that follows, the current way is clearer and more pythonic than the proposed API:


    # Proposed way
    subscriber = request.query['subscriber']
    if subscribers.discard(subscriber):
        print('Unsubscribed')
    else:
        print('Subscriber not found')

    # Current way
    subscriber = request.query['subscriber']
    if subscriber in subscribers:
        subscribers.remove(subscriber)
        print('Unsubscribed')
    else:
        print('Subscriber not found')

Note, the latter way is also what we would use if subscribers were a dictionary (using del instead of remove). 
   
The proposed API is also at odds with the original intent of discard() as meaning "we don't care whether the element is present or not, we just want it gone".
msg329048 - (view) Author: (tzickel) * Date: 2018-11-01 07:05
I would think that the .discard is the equivalent of .pop in dict. (instead of wasting time once checking and once removing, also the data in a set is the data, there is no value to check). 

Even the standard lib has lots of usage of dict.pop(key, None) to not throw an exception. (instead of not using None, and catching exception).

What sets this apart from other mutating APIs is that it does not throw an exception.
History
Date User Action Args
2022-04-11 14:59:07adminsetgithub: 79298
2018-11-01 07:05:37tzickelsetmessages: + msg329048
2018-10-31 06:51:06rhettingersetstatus: open -> closed
resolution: rejected
messages: + msg328972

stage: resolved
2018-10-31 03:52:31Windson Yangsetnosy: + Windson Yang
messages: + msg328964
2018-10-31 03:39:09rhettingersetassignee: rhettinger
2018-10-30 19:46:34serhiy.storchakasetnosy: + rhettinger, serhiy.storchaka
messages: + msg328939
2018-10-30 18:50:32tzickelcreate