Passing Python slice syntax around to functions

倖福魔咒の 提交于 2019-11-30 07:25:47

问题


In Python, is it possible to encapsulate exactly the common slice syntax and pass it around? I know that I can use slice or __slice__ to emulate slicing. But I want to pass the exact same syntax that I would put in the square brackets that would get used with __getitem__.

For example, suppose I wrote a function to return some slice of a list.

def get_important_values(some_list, some_condition, slice):
    elems = filter(some_condition, some_list)
    return elems[slice]

This works fine if I manually pass in a slice object:

In [233]: get_important_values([1,2,3,4], lambda x: (x%2) == 0, slice(0, None))
Out[233]: [2, 4]

But what I want to let the user pass is exactly the same slicing they would have used with __getitem__:

get_important_values([1,2,3,4], lambda x: (x%2) == 0, (0:-1) )

# or

get_important_values([1,2,3,4], lambda x: (x%2) == 0, (0:) )

Obviously this generates a syntax error. But is there any way to make this work, without writing my own mini parser for the x:y:t type slices, and forcing the user to pass them as strings?

Motivation

I could just make this example function return something directly sliceable, such as filter(some_condition, some_list), which will be the whole result as a list. In my actual example, however, the internal function is much more complicated, and if I know the slice that the user wants ahead of time, I can greatly simplify the calculation. But I want the user to not have to do much extra to tell me the slice ahead of time.


回答1:


Perhaps something along the following lines would work for you:

class SliceMaker(object):
  def __getitem__(self, item):
    return item

make_slice = SliceMaker()

print make_slice[3]
print make_slice[0:]
print make_slice[:-1]
print make_slice[1:10:2,...]

The idea is that you use make_slice[] instead of manually creating instances of slice. By doing this you'll be able to use the familiar square brackets syntax in all its glory.




回答2:


In short, no. That syntax is only valid in the context of the [] operator. I might suggest accepting a tuple as input and then pass that tuple to slice(). Alternatively, maybe you could redesign whatever you're doing so that get_important_values() is somehow implemented as a sliceable object.

For example, you could do something like:

class ImportantValueGetter(object):
    def __init__(self, some_list, some_condition):
        self.some_list = some_list
        self.some_condition = some_condition

    def __getitem__(self, key):
        # Here key could be an int or a slice; you can do some type checking if necessary
        return filter(self.some_condition, self.some_list)[key]

You can probably do one better by turning this into a Container ABC of some sort but that's the general idea.




回答3:


One way (for simple slices) would be to have the slice argument either be a dict or an int,

ie

get_important_values([1, 2, 3, 4], lambda x: (x%2) == 0, {0: -1})

or

get_important_values([1, 2, 3, 4], lambda x: (x%2) == 0, 1)

then the syntax would stay more or less the same.

This wouldn't work though, for when you want to do things like

some_list[0:6:10..]


来源:https://stackoverflow.com/questions/13706258/passing-python-slice-syntax-around-to-functions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!