gpt4 book ai didi

python - 子类别 list

转载 作者:太空狗 更新时间:2023-10-30 02:50:41 27 4
gpt4 key购买 nike

我想创建一个数据集类,它基本上是一个样本列表。
但是我需要覆盖每个插入操作到DataSet。
有没有什么简单的方法可以做到这一点,而不需要编写我自己的append、extend、iadd等?
更新:我想给每个样本添加一个反指针,保持数据集中的样本索引。这是我使用的处理算法所需要的。我有一个解决方案,但它看起来不合法——一个renumber()函数——它确保了backpointer是有效的。

最佳答案

我不知道怎样做你所要求的——在不重写变异的情况下重写它们。然而,使用类装饰器,您可以“自动化”重写版本(假设每个版本都可以通过在基类中包装相应的方法来实现),所以这还不算太糟……
例如,假设您要做的是添加一个“modified”标志,如果自上次调用.save以来数据可能已更改,则为true(您的一种方法,它将数据持久化并将self.modified设置为false)。
然后…:

def wrapMethod(cls, n):
f = getattr(cls, n)
def wrap(self, *a):
self.dirty = True
return f(self, *a)
return wrap

def wrapListMutators(cls):
for n in '''__setitem__ __delitem__ __iadd__ __imul__
append extend insert pop remove reverse sort'''.split():
f = wrapMethod(cls, n)
setattr(cls, n, f)
return cls

@wrapListMutators
class DataSet(list):
dirty = False
def save(self): self.dirty = False

此语法要求Python2.6或更高版本,但是在早期的Python版本中(仅支持 def语句上的decorator,而不支持 class语句;甚至是不支持decorator的非常旧的版本),您只需将最后一部分( class语句)更改为:
class DataSet(list):
dirty = False
def save(self): self.dirty = False
DataSet = wrapListMutators(DataSet)

注意,整洁的decorator语法只是普通函数调用(以类为参数并重新分配它)之上的少量语法糖。
编辑:现在您已经编辑了您的问题,以澄清您的确切要求——在每个项目上维护一个字段 bp,这样,对于所有 itheset[i].bp == i——更容易权衡各种方法的利弊。
您可以修改我草拟的方法,但在调用包装方法之前,不要使用 self.dirty赋值,在其之后有一个 self.renumber()调用,即:
def wrapMethod(cls, n):
f = getattr(cls, n)
def wrap(self, *a):
temp = f(self, *a)
self.renumber()
return temp
return wrap

这符合你的要求,但在很多情况下,它将比必要的做更多的工作:例如,当你 append一个项目时,这不必要的“重新编号”所有现有的(对于他们已经拥有的相同的值)。但是,任何完全自动化的方法如何能够“知道”哪些项目(如果有的话)必须重新计算的 .bp,而不需要 O(N)的努力?至少它必须查看它们中的每一个(因为您不想单独编写代码,例如, appendvs insert&c),这已经是 O(N)
因此,只有当列表的每一个更改都可以 O(N)时(基本上只有当列表总是很小和/或不经常更改时),这才是可以接受的。
一个更富有成效的想法可能是不总是保持 .bp值,而是在需要的时候“及时”。使 bp成为一个(只读)属性,调用一个方法来检查容器是否“脏”(容器中的“脏”标志是使用我已经给出的自动代码维护的),然后才对容器重新编号(并将其“脏”属性设置为 False)。
当列表通常会发生一系列更改时,这将很好地工作,只有这样,您才需要访问项目“ bp一段时间,然后再进行一系列更改,等等。在实际容器中,这种更改和读取之间的快速交替并不少见,但只有您才能知道它是否适用于您的特定情况!
为了达到这个效果,我认为你需要做一些手工编码,以达到一般的方法来利用频繁的特殊情况。例如, append可能经常被调用,而且在特殊情况下要做的工作量非常小,因此编写这两行或三行代码(不为这种情况设置脏位)可能是值得的。
一个警告:如果列表中的任何项出现两次(当然这是完全可能的,除非您采取预防措施避免它(您可以在 append中很容易地诊断它),并且保留一组已经看到的元素并对任何重复项提出一个异常,否则任何方法都不会起作用(实际上您的需求是自相矛盾的)对你来说还不算太晚,更难诊断“飞逝”,也就是说,在变异的时候,如果你需要的话,会导致复制。也许您可以放宽您的要求,这样,如果一个项出现两次,就可以了, renumber可以只指示其中一个索引;或者将 bp设置为元素出现的一组索引(这也将为从不在列表中的元素获取 bp提供一种平滑的方法)。等等,等等;我建议你考虑(并记录!)所有这些角落的情况深入--正确的表现之前!

关于python - 子类别 list ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/970425/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com