Skip to content

Commit 180721f

Browse files
committed
relax operator[] for tuples, lists, and sequences
object_api::operator[] has a powerful overload for py::handle that can accept slices, tuples (for NumPy), etc. Lists, sequences, and tuples provide their own specialized operator[], which unfortunately disables this functionality. This is accidental, and the purpose of this commit is to re-enable the more general behavior. This commit is tangentially related to the previous one in that it makes py::handle/py::object et al. behave more like their Python counterparts.
1 parent 5954523 commit 180721f

File tree

3 files changed

+12
-0
lines changed

3 files changed

+12
-0
lines changed

include/pybind11/pytypes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,7 @@ class tuple : public object {
11831183
}
11841184
size_t size() const { return (size_t) PyTuple_Size(m_ptr); }
11851185
detail::tuple_accessor operator[](size_t index) const { return {*this, index}; }
1186+
detail::item_accessor operator[](handle h) const { return object::operator[](h); }
11861187
detail::tuple_iterator begin() const { return {*this, 0}; }
11871188
detail::tuple_iterator end() const { return {*this, PyTuple_GET_SIZE(m_ptr)}; }
11881189
};
@@ -1220,6 +1221,7 @@ class sequence : public object {
12201221
PYBIND11_OBJECT_DEFAULT(sequence, object, PySequence_Check)
12211222
size_t size() const { return (size_t) PySequence_Size(m_ptr); }
12221223
detail::sequence_accessor operator[](size_t index) const { return {*this, index}; }
1224+
detail::item_accessor operator[](handle h) const { return object::operator[](h); }
12231225
detail::sequence_iterator begin() const { return {*this, 0}; }
12241226
detail::sequence_iterator end() const { return {*this, PySequence_Size(m_ptr)}; }
12251227
};
@@ -1232,6 +1234,7 @@ class list : public object {
12321234
}
12331235
size_t size() const { return (size_t) PyList_Size(m_ptr); }
12341236
detail::list_accessor operator[](size_t index) const { return {*this, index}; }
1237+
detail::item_accessor operator[](handle h) const { return object::operator[](h); }
12351238
detail::list_iterator begin() const { return {*this, 0}; }
12361239
detail::list_iterator end() const { return {*this, PyList_GET_SIZE(m_ptr)}; }
12371240
template <typename T> void append(T &&val) const {

tests/test_pytypes.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,4 +289,8 @@ TEST_SUBMODULE(pytypes, m) {
289289
l.append(a << b);
290290
return l;
291291
});
292+
293+
m.def("test_list_slicing", [](py::list a) {
294+
return a[py::slice(0, -1, 2)];
295+
});
292296
}

tests/test_pytypes.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,8 @@ def test_number_protocol():
246246
li = [a == b, a != b, a < b, a <= b, a > b, a >= b, a + b,
247247
a - b, a * b, a / b, a | b, a & b, a ^ b, a >> b, a << b]
248248
assert m.test_number_protocol(a, b) == li
249+
250+
251+
def test_list_slicing():
252+
li = list(range(100))
253+
assert li[::2] == m.test_list_slicing(li)

0 commit comments

Comments
 (0)