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: Add PyList_Remove() in listobject.c
Type: Stage: resolved
Components: C API Versions: Python 3.10
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: serhiy.storchaka, shihai1991, vstinner
Priority: normal Keywords:

Created on 2020-09-27 13:30 by shihai1991, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (6)
msg377566 - (view) Author: Hai Shi (shihai1991) * (Python triager) Date: 2020-09-27 13:30
Do we need add PyList_Remove() in C level? same thing like list.remove().
As victor comment in: https://github.com/python/cpython/pull/19069#discussion_r491893466.
msg377568 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2020-09-27 13:52
You always can use PyObject_CallMethod(). It is not a method called in tight loop for which the overhead of calling method is significant.
msg377573 - (view) Author: Hai Shi (shihai1991) * (Python triager) Date: 2020-09-27 15:33
> You always can use PyObject_CallMethod(). It is not a method called in tight loop for which the overhead of calling method is significant.
Thanks, serhiy. You are right.
To PR19069, it's fine to use `PyList_SetSlice` or `PyObject_CallMethod`.
We don't have the enough reason to add `PyList_Remove()`,so I decided close this bpo now.

PS: I attach a PR which have add `PyList_Remove` in here in case we will meet another appropriate user case somedays: https://github.com/python/cpython/compare/master...shihai1991:add_PyList_Remove?expand=1
msg377644 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-09-28 22:46
I proposed to Hai Shi in his PR to add PyList_Remove() since I was surprised that the feature is exposed in Python but not at the C level.

> You always can use PyObject_CallMethod(). It is not a method called in tight loop for which the overhead of calling method is significant.

He reimplemented the function by copying items into a new list except of the item which should be removed.

I expect that PyList_SetSlice() is more efficient than creating a new list, it modifies the list in-place.

I'm fine with rejecting this issue.
msg377680 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2020-09-29 19:09
PyList_SetSlice() allows to remove an item by index, as in `del a[i]`. list.remove() searches the item by value and removes the first occurrence. You can implement it via PySequence_Index() and PyList_SetSlice(), but it is more convenient to just call the method.

There is no C API for most methods of builtin types. C API is only added for the following cases:

1. Conversion between Python and C values. There is no other way to do this. PyLong_AsLong() and PyLong_FromLong().
2. Access to general protocols. PyNumber_Add(), PyObject_GetAttr(), PySequence_etc.
3. Specialized versions for concrete types if they are much more convenient and performant. They are also often preceded the more general API. PyObject_GetItem() -> PySequence_GetItem() -> PyList_GetItem() -> PyList_GET_ITEM().
4. High-level common operations. From PyImport_ImportModule() to PyRun_SimpleString().
msg377744 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-10-01 10:45
> it is more convenient to just call the method

Calling a Python method in Python is not convenient nor efficient.

For example, PyObject_CallMethod() has to decode a name from UTF-8 and then needs a lookup into the type dictionary. The list.remove() raises a exception if the item is not found, whereas PyCodec_Unregister() does nothing if the codec search function is not found: the exception is ignored.

It's also about correctness, looking for an item in a list can be tricky if the list size changes during the lookup, or Python can crash if it uses a borrowed reference whereas a list item is destroyed. There were tons of such bugs in the dict implementation. list.remove() doesn't look safe, but I would prefer to avoid having to fix the same bugs in copies of similar functions.

If a public function is not justified, what about an internal function?
History
Date User Action Args
2022-04-11 14:59:36adminsetgithub: 86037
2020-10-01 10:45:43vstinnersetmessages: + msg377744
2020-09-29 19:09:39serhiy.storchakasetmessages: + msg377680
2020-09-28 22:46:59vstinnersetmessages: + msg377644
2020-09-27 15:33:21shihai1991setstatus: open -> closed
resolution: rejected
messages: + msg377573

stage: resolved
2020-09-27 13:52:48serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg377568
2020-09-27 13:30:06shihai1991create