Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do slices really must have step size of 1? #90

Open
azmeuk opened this issue May 14, 2018 · 1 comment
Open

Do slices really must have step size of 1? #90

azmeuk opened this issue May 14, 2018 · 1 comment

Comments

@azmeuk
Copy link
Member

azmeuk commented May 14, 2018

As I found, OOBTreeItems cannot be sliced backwards or with a step greater than 1, seemingly due to this line.

In [1]: from BTrees.OOBTree import OOBTree

In [2]: a = OOBTree({1:"one", 2:"two", 3:"three"})

In [3]: list(a.keys()[1:2:-1])
---------------------------------------------------------------------------
RuntimeError                              
Traceback (most recent call last)
<ipython-input-3-2e5a94b46d47> in <module>()
----> 1 list(a.keys()[1:2:-1])

RuntimeError: slices must have step size of 1

Is there any plans to develop this feature? Does it require a lot of work?

For the moment, I use workarounds like reversed(a.keys()[1:2]) to simulate a -1 step, but I suppose it would be more efficient if that was coded in C?

@azmeuk azmeuk changed the title Do really slices must have step size of 1? Do slices really must have step size of 1? May 14, 2018
@jamadden
Copy link
Member

In the C extension, slices are implemented by just returning a new Items object, just like a plain call to keys():

>>> a.keys()
<OOBTreeItems at 0x11084fc40>
>>> a.keys()[1:2]
<OOBTreeItems at 0x10fcc2ee0>

That object uses the same underlying bucket storage as the tree, and it doesn't have any place to store the extra state needed to track a different step size, so that's the first problem.

More serious, though, is that BTreeItems support indexed subscripting of themselves:

>>> bt = OOBTree()
>>> bt['a'] = 1
>>> bt.keys()[0]
'a'

They implement iteration using that subscripting support through the old iteration protocol. So the object would have to be changed to understand how to compute "real" indexes based on a different step size, which sounds like it could get ugly.

I'll note that the Python implementation just punts the whole problem over to list for any slice:

>>> from BTrees.OOBTree import OOBTreePy
>>> a = OOBTreePy({1:"one", 2:"two", 3:"three"})
>>> a.keys()
<BTrees._base._TreeItems object at 0x1026fb858>
>>> a.keys()[1:2]
[2]

That loads the whole tree into memory, though, which is not efficient. But it works (for small cases...) and probably wouldn't be that hard to adopt in C if we wanted to. (Either that or the Python implementation should enforce the same restriction.)

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

No branches or pull requests

2 participants