在 Python 中使用字符串作为切片索引? (TypeError:切片索引必须是整数或 None 或具有 __index__ 方法)

Posted

技术标签:

【中文标题】在 Python 中使用字符串作为切片索引? (TypeError:切片索引必须是整数或 None 或具有 __index__ 方法)【英文标题】:Use strings as slice indices in Python ? (TypeError: slice indices must be integers or None or have an __index__ method) 【发布时间】:2020-05-02 06:03:44 【问题描述】:

我有一个排序数组:

arr = ['Alexander', 'Belman', 'Erik', 'Nicholas', ... , 'Zahir']

我想做这样的事情:

arr['B':'M'] # ['Belman', 'Erik']

如何创建一个类并实现

__getitem__
__index__

以正确的方式实现这一目标?

我正在考虑使用类似的东西

def __getitem__(self, key):
    if isinstance(key, slice):
        return [self.list[i] for i in range(key.start, key.stop)]
    return self.list[key]

但我不知道如何索引字符串。如何创建一个

__index__

将二进制搜索应用于self.list 并返回正确索引的方法?

【问题讨论】:

我不知道为什么arr['B':'M'] 会提供您提供的输出。也许你的意思是arr['B':'N']?另外,如果多个字符串以同一个字母开头会怎样? 为什么要这样做?你能提供更多背景信息吗? python 作为bisect 问题定义不够精确。例如,您是否希望能够使用长度超过一个字符的字符串,例如:arr['Bel':'Ni']? 这是你想要的Indexing Lists in Python With an Integer or Object’s Name的一个例子吗?它覆盖 getitem 【参考方案1】:

我认为你可以像下面这样简单的实现:

from collections import UserList

class MyList(UserList):
    def __getitem__(self, key):
        if isinstance(key, slice):
            return [e for e in self.data if key.start <= e < key.stop]
        # TODO implement the rest of the usecases and/or error handling...
        #      for now slicing with integers will miserably fail,
        #      and basic integer indexing returns None

arr = MyList(['Alexander', 'Belman', 'Erik', 'Nicholas', 'Zahir'])
print(arr['B':'M'])

哪个会输出

['Belman', 'Erik']

同样,

print(arr['Alex':'Er'])

会输出

['Alexander', 'Belman']

请注意,我使用 key.start &lt;= e &lt; key.stop 是为了符合整个 python 中使用的 inclusive:exclusive ([)) 行为。

另外请注意,我只实现了字符串切片用例。您可以根据需要实现其他用例和错误处理。

【讨论】:

很好的解决方案。 Indexing Lists in Python With an Integer or Object’s Name 展示了如何通过将其委托给列表中的 `__getitem__` 来处理“现在使用整数切片将严重失败”的问题。【参考方案2】:

我还使用 numpy 发布了我的二进制搜索解决方案

class Stock():

    def __init__(self, name, date):
        self.name = name
        self.date = np.array(date)


    def __getitem__(self, key):

        if isinstance(key, slice):
            if key.start is not None and key.stop is not None: 
                return self.date[np.searchsorted(self.date, key.start, side='left', sorter=None):np.searchsorted(self.date, key.stop, side='left', sorter=None)]
            elif key.start is not None:
                return self.date[np.searchsorted(self.date, key.start, side='left', sorter=None):]
            elif key.stop is not None:
                return self.date[:np.searchsorted(self.date, key.stop, side='left', sorter=None)]
            else:
                return self.date[:]

        i = np.searchsorted(self.date, key, side='left', sorter=None)
        if key != self.date[i]:
            raise KeyError('key:  was not found!'.format(key))
        else:
            return self.date[i]



aapl = Stock('aapl', ['2010','2012', '2014', '2016', '2018'])

print(aapl['2011':])
print(aapl['2014':'2017'])
print(aapl[:'2016'])
print(aapl['2010'])
print(aapl['2013'])

'''
['2012' '2014' '2016' '2018']
['2014' '2016']
['2010' '2012' '2014']
2010
Traceback (most recent call last):
  File "C:\Users\...\Desktop\...\stock.py", line ##, in <module>
    print(aapl['2013'])
  File "C:\Users\...\Desktop\...\stock.py", line ##, in __getitem__
    raise KeyError('key:  was not found!'.format(key))
KeyError: 'key: 2013 was not found!'
'''

【讨论】:

以上是关于在 Python 中使用字符串作为切片索引? (TypeError:切片索引必须是整数或 None 或具有 __index__ 方法)的主要内容,如果未能解决你的问题,请参考以下文章

55个案例:吃透Python列表的索引和切片

python中的字符串切片

Python字符串切片索引 - 切片到字符串的结尾

流畅的Python——切片

乐哥学AI_Python:Numpy索引,切片,常用函数

如何用Python字符串进行切片操作?