围绕列表的包装器类,用于跟踪i是否发生了新的更改

2024-10-01 17:39:25 发布

您现在位置:Python中文网/ 问答频道 /正文

需要以下行中的内容:

class CustomList(List):
    def __init__(self):
        self.changeID = 0  # This value increases whenever a value is changed in the custom list

我正在寻找一种计算成本很低的方法,来找出列表是否改变了我上次访问它时的状态。这样做的方法可以是每次更新列表的值时,都更新与列表关联的一些changeID 对列表的更改是以下内容之一:
-附加了值
-值已被删除
-值在某个索引处被替换

我所期望的是:

l1 = CustomList()  # changeId = 0 at beginning
l1.append(2)       # changeId updates to 1
l1.append(7)       # changeId updates to 2
l1.append(30)      # changeId updates to 3
l1[1] = 9          # changeId updates to 4 . l1 = [2, 9, 30]
del l1[0]          # changeId updates to 5 . l1 = [9,30]
l1.remove(9)       # changeId updates to 6 . l1 = [30]
l1.pop()           # changeId updates to 7 . l1 = []

print(l1.changeID)  # changeID needs to be accessible via the object (of course)

我试图为此编写一些代码,但没有成功。请帮忙


Tags: theto方法selfl1内容列表value
1条回答
网友
1楼 · 发布于 2024-10-01 17:39:25

您必须修补个别方法(我可能遗漏了一些,请进行研究):

class CustomList(list):
    def __init__(self):
        self.change_id = 0
        super().__init__()

    def append(self, obj):
        self.change_id += 1
        super().append(obj)

    def __setitem__(self, key, value):
        self.change_id += 1
        super().__setitem__(key, value)

    def remove(self, obj):
        self.change_id += 1
        super().remove(obj)

    def pop(self, index):
        self.change_id += 1
        super().pop(index)

    def insert(self, index, obj):
        self.chgange_id += 1
        super().insert(index, obj)

    def __delitem__(self, key):
        self.change_id += 1
        super().__delitem__(key)

l1 = CustomList()
l1.append(2)
l1.append(7)
l1.append(30)
l1[1] = 9
del l1[0]
l1.remove(9)
l1.pop(0)
print(l1.change_id)
# 7

这段代码有很多重复,我们可以使用decorator:

def increase_change_counter(func):
    def inner(self, *args, **kwargs):
        self.change_id += 1
        return func(self, *args, **kwargs)
    return inner

class CustomList(list):
    def __init__(self):
        self.change_id = 0
        super().__init__()

    @increase_change_counter
    def append(self, obj):
        super().append(obj)

    @increase_change_counter
    def __setitem__(self, key, value):
        super().__setitem__(key, value)

    @increase_change_counter
    def remove(self, obj):
        super().remove(obj)

    @increase_change_counter
    def pop(self, index):
        super().pop(index)

    @increase_change_counter
    def insert(self, index, obj):
        super().insert(index, obj)

    @increase_change_counter
    def __delitem__(self, key):
        super().__delitem__(key)


l1 = CustomList()
l1.append(2)
l1.append(7)
l1.append(30)
l1[1] = 9
del l1[0]
l1.remove(9)
l1.pop(0)
print(l1.change_id)
# 7

显然,这对于一项简单的任务来说还是太长了

我们可以试试这个:

class CustomList(list):
    def __init__(self):
        self.change_id = 0
        super().__init__()

    def __getattribute__(self, item):
        if item in ('append', 'remove', 'pop', 'insert'):
            self.change_id += 1
        return super().__getattribute__(item)

但是l1[1] = 9del l1[0]不会被__getattribute__捕获

因此,也许是一种组合:

def increase_change_counter(func):
    def inner(self, *args, **kwargs):
        self.change_id += 1
        return func(self, *args, **kwargs)
    return inner

class CustomList(list):
    def __init__(self):
        self.change_id = 0
        super().__init__()

    @increase_change_counter
    def __setitem__(self, key, value):
        super().__setitem__(key, value)

    @increase_change_counter
    def __delitem__(self, key):
        super().__delitem__(key)

    def __getattribute__(self, item):
        if item in ('append', 'remove', 'pop', 'insert'):
            self.change_id += 1
        return super().__getattribute__(item)

l1 = CustomList()
l1.append(2)
l1.append(7)
l1.append(30)
l1[1] = 9
del l1[0]
l1.remove(9)
l1.pop(0)
print(l1.change_id)
# 7

相关问题 更多 >

    热门问题