现在我有以上源代码:
class Stats(object):
def __init__(self):
self._pending = []
self._done = []
@property
def pending(self):
return self._pending
这些列表的填充方式对我的问题并不重要。
情况是,我以这种方式获得了这些列表的冠军:
stats = Stats()
// code to fill the lists
stats.pending[2:10]
这里的问题是,我希望获得与我检索到的元素一样多的元素。在上面的示例中,我期望一个包含8个元素(10-2)的sublist。
当然,实际上,如果列表较短,我将获得少于8个元素。
所以,我需要的是:
- 当列表有足够的项目时,它将返回相应的sublist。
- 当列表较短时,它将返回一个带有预期长度的子列表,并充满了原始列表的最后元素和默认值(例如无)。
这样,如果我这样做:
pending_tasks = stats.pending[44:46]
,待处理列表仅包含30个元素,它应返回两个默认元素的列表,例如:[none,none];而不是空列表([]),这是列表的默认行为。
我想我已经知道如何在普通方法/函数中进行操作,但是我想以最干净的方式进行操作,并尝试遵循@property方法。
非常感谢!
这并不容易,因为切片操作是您要修改的操作,并且在property
返回原始列表之后发生了。不过,这并非不可能,您只需要用另一个对象包装常规列表,以照顾您的切片。将会变得多么容易或困难取决于您需要包装器要实现的列表接口中的多少。如果您只需要索引和切片,这真的很容易:
class PadSlice(object):
def __init__(self, lst, default_value=None):
self.lst = lst
self.default_value
def __getitem__(self, index):
item = getitem(self.lst, index)
if isinstance(index, slice):
expected_length = (index.stop - index.start) // (index.step or 1)
if len(item) != expected_length:
item.extend([default_value] * (expected_length - len(item)))
return item
此代码可能对负步切片或未指定终点之一的切片不正常(它具有检测省略的步骤,因为这很常见,它确实具有逻辑)。如果这对您很重要,您可能可以修复那些角案件。
这并不容易。您返回的对象(列表)如何知道稍后将如何切片?但是,您可以子类list
,并且可以覆盖__getitem__
和__getslice__
(仅Python2):
class L(list):
def __getitem__(self, key):
if isinstance(key, slice):
return [list(self)[i] if 0 <= i < len(self) else None for i in xrange(key.start, key.stop, key.step or 1)]
return list(self)[key]
def __getslice__(self, i, j):
return self.__getitem__(slice(i, j))
这将用None
粘贴所有切片,与负索引和步骤!= 1
完全兼容。在您的属性中,返回实际列表的L
版本:
@property
def pending(self):
return L(self._pending)
您可以构造一个新类,该类是list
的子类。然后,您可以将__getitem__
魔术方法超载以将[]
运算符重载到适当的行为。考虑list
的这个子类称为MyList
:
class MyList(list):
def __getitem__(self, index):
"""Modify index [] operator"""
result = super(MyList, self).__getitem__(index)
if isinstance(index, slice):
# Get sublist length.
if index.step: # Check for zero to avoid divide by zero error
sublist_len = (index.stop - index.start) // index.step
else:
sublist_len = (index.stop - index.start)
# If sublist length is greater (or list is shorter), then extend
# the list to length requested with default value of None
if sublist_len > len(self) or index.start > len(self):
result.extend([None for _ in range(sublist_len - len(result))])
return result
然后,您只需更改pending
方法以返回MyList
类型而不是list
。
class Stats(object):
@property
def pending(self):
return MyList(self._pending)
希望这会有所帮助。