我正在用 Python 制作一个容器类,它要么继承自 list
,要么只实现所有标准列表方法(我真的不在乎是哪个)。
我将如何创建一个仅作用于从切片返回的项目的方法?我已经能够创建一个将作用于整个容器的方法(见下文),但我似乎无法弄清楚如何只作用于切片。
我正在使用 python 2.7.6 并在我的所有代码中使用 from __future__ import print_function, division
。
示例代码:
from __future__ import print_function, division
import itertools
class MyContainerClass(list):
""" For now, I'm inheriting from list. Is this my problem? """
def __init__(self, data_array):
list.__init__(self, data_array)
def __getitem__(self, *args):
arg = args[0]
# specific indices MyContainerClass[0, 3, 5] => indexes 0, 3, and 5
if isinstance(arg, (list, tuple)) and not isinstance(arg[0], bool):
return [list.__getitem__(self, _i) for _i in arg]
# standard slice notation
elif isinstance(arg, slice):
return list.__getitem__(self, arg)
# Using an array mask MyContainerClass[[True, False, False,...,True]] => index 0 and -1]
elif isinstance(arg[0], bool): # or isinstance(arg, np.ndarray):
return list(itertools.compress(self, arg))
else:
# I'll eventually replace this with and exception raise.
return 'error'
def my_method(self):
"""
Will act on entire list, but I want it to act on only what's
returned by the slice (which may be the entire list in some cases).
"""
return "a, ".join([str(_i) for _i in self])
这是我想要的用法示例:
>>> data = MyContainerClass([1, 2, 3, 4, 5, 6, 7])
>>> data[5:]
[6, 7]
>>> data.my_method() # This works as expected
"1a, 2a, 3a, 4a, 5a, 6a, 7"
>>> data[0:3].my_method() # Doesn't work
"1a, 2a, 3" # but should return this
看起来一切正常。谢谢一群人!这是我想出的:
from __future__ import print_function, division
import itertools
class MyContainerClass(list):
"""
"""
def __init__(self, array):
if isinstance(array, int):
list.__init__(self, [array])
else:
list.__init__(self, array)
def __getitem__(self, arg):
# Standard Slice notation
if isinstance(arg, slice):
retval = super(MyContainerClass, self).__getitem__(arg)
# specific indices
elif isinstance(arg, (list, tuple)) and not isinstance(arg[0], bool):
retval = [list.__getitem__(self, _i) for _i in arg]
# a single specific index
elif isinstance(arg, int):
retval = list.__getitem__(self, arg)
# an array mask of T/F values
elif isinstance(arg[0], bool): # or isinstance(arg, np.ndarray):
retval = list(itertools.compress(self, arg))
# raise an error on unknown
else:
raise SyntaxError("Unknown notation for list slice or index")
retval = type(self)(retval)
return retval
def __getslice__(self, i, j):
# Python 2 built-in types only
return self.__getitem__(slice(i, j))
def my_method(self):
return "a, ".join([str(_i) for _i in self])
并且表现得像:
>>> data = MyContainerClass([1, 2, 3, 4, 5, 6, 7])
>>> mask = [True, True, False, True, False, False, False]
>>> print(data)
[1, 2, 3, 4, 5, 6, 7]
>>> print(type(data[5:]))
<class '__main__.MyContainerClass'>
>>> print(data.my_method())
1a, 2a, 3a, 4a, 5a, 6a, 7
>>> print(data[0:5].my_method())
1a, 2a, 3a, 4a, 5
>>> print(data[1, 5, 2].my_method())
2a, 6a, 3
>>> print(data[mask].my_method())
1a, 2a, 4
>>> print(data[2].my_method())
3
最佳答案
您必须确保您的 __getitem__
再次返回您的类型:
class MyContainerClass(list):
""" For now, I'm inheriting from list. Is this my problem? """
def __init__(self, data_array):
list.__init__(self, data_array)
def my_method(self):
"""
Will act on entire list, but I want it to act on only what's
returned by the slice (which may be the entire list in some cases).
"""
return "a, ".join([str(_i) for _i in self])
def __getitem__(self, index):
retval = super(MyContainerClass, self).__getitem__(index)
if isinstance(index, slice):
retval = type(self)(retval)
return retval
def __getslice__(self, i, j):
# Python 2 built-in types only
return self.__getitem__(slice(i, j))
额外的__getslice__
method仅在 Python 2 中需要,并且仅当您从已实现 __getslice__
的类型继承时才需要。 list
就是这样一种类型。
演示:
>>> data = MyContainerClass([1, 2, 3, 4, 5, 6, 7])
>>> data[:5]
[1, 2, 3, 4, 5]
>>> type(data[:5])
<class '__main__.MyContainerClass'>
>>> data.my_method()
'1a, 2a, 3a, 4a, 5a, 6a, 7'
>>> data[:3].my_method()
'1a, 2a, 3'
关于Python:是否可以有一个类方法作用于类的一部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25511436/