- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在运行 Python 2.7.10。
我需要拦截列表中的更改。 “更改”是指任何在浅层意义上修改列表的内容(如果列表由相同顺序的相同对象组成,则列表不会更改,而不管这些对象的状态如何;否则,它是)。我不需要了解列表如何发生了变化,只要它发生了变化即可。所以我只是确保我可以检测到它,然后让基本方法完成它的工作。这是我的测试程序:
class List(list):
def __init__(self, data):
list.__init__(self, data)
print '__init__(', data, '):', self
def __getitem__(self, key):
print 'calling __getitem__(', self, ',', key, ')',
r = list.__getitem__(self, key)
print '-->', r
return r
def __setitem__(self, key, data):
print 'before __setitem__:', self
list.__setitem__(self, key, data)
print 'after __setitem__(', key, ',', data, '):', self
def __delitem__(self, key):
print 'before __delitem__:', self
list.__delitem__(self, key)
print 'after __delitem__(', key, '):', self
l = List([0,1,2,3,4,5,6,7]) #1
x = l[5] #2
l[3] = 33 #3
x = l[3:7] #4
del l[3] #5
l[0:4]=[55,66,77,88] #6
l.append(8) #7
案例 #1、#2、#3 和 #5 的工作符合我的预期; #4、#6 和#7 没有。程序打印:
__init__( [0, 1, 2, 3, 4, 5, 6, 7] ): [0, 1, 2, 3, 4, 5, 6, 7]
calling __getitem__( [0, 1, 2, 3, 4, 5, 6, 7] , 5 ) --> 5
before __setitem__: [0, 1, 2, 3, 4, 5, 6, 7]
after __setitem__( 3 , 33 ): [0, 1, 2, 33, 4, 5, 6, 7]
before __delitem__: [0, 1, 2, 33, 4, 5, 6, 7]
after __delitem__( 3 ): [0, 1, 2, 4, 5, 6, 7]
我对#7 并不感到非常惊讶:append
可能是以一种特别的方式实现的。但是对于#4 和#6 我很困惑。 __getitem__
文档说:“调用以实现 self[key] 的评估。对于序列类型,接受的键应该是整数和 slice 对象。”(我的重点)。对于 __setitem__
:“与 __getitem__
()” 相同的注释,我认为这意味着 key
可以也是一片。
我的推理有什么问题?如有必要,我准备重写每个列表修改方法(附加、扩展、插入、弹出等),但是应该重写什么以捕获类似 #6 的内容?
我知道 __setslice__
等的存在。但这些方法自 2.0 以来已被弃用 ...
嗯。我再次阅读了有关 __getslice__
、__setslice__
等的文档,我发现了这个令人毛骨悚然的声明:
“(但是,CPython 中的内置类型目前仍然实现了 __getslice__()
。因此,在实现切片时,您必须在派生类中覆盖它。)”
这是解释吗?这是在说“好吧,方法已被弃用,但为了在 2.7.10 中实现与 2.0 中相同的功能,您仍然必须覆盖它们”? las,那您为什么不赞成使用它们? future 将如何运作?是否有一个“列表”类——我不知道——我可以扩展并且不会带来这种不便?我真正需要重写什么以确保捕获每个列表修改操作?
最佳答案
问题是您要对内置函数进行子类化,因此必须处理一些问题。在深入探讨该问题之前,我将直接进入“现代”方式:
How will things work in the future? Is there a "list" class - that I am not aware of - that I could extend and would not present this inconvenience?
是的,有标准库 Abstract Base Classes .您可以通过使用 ABC 来避免由子类化内置 list
引起的丑陋的并发症。对于类似列表的东西,尝试子类化 MutableSequence
:
from collections import MutableSequence
class MyList(MutableSequence):
...
现在你应该只需要处理 __getitem__
和 friend 的切片行为。
如果您想继续继承内置的 list
,请继续阅读...
您的猜测是正确的,您将需要覆盖 __getslice__
和 __setslice__
。 language reference explains why你已经看到了:
However, built-in types in CPython currently still implement
__getslice__()
. Therefore, you have to override it in derived classes when implementing slicing.
请注意,l[3:7]
将 Hook 到 __getslice__
,而其他等效的 l[3:7:]
将 Hook 进入 __getitem__
,所以你必须处理在这两种方法中接收切片的可能性......呻吟!
关于python - __getitem__、__setitem__ 如何处理切片?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32772755/
我希望能够拦截函数内的变量赋值并执行自定义代码。我试过如下创建自定义字典: class userdict(dict): def __setitem__(self, key, value):
我正在尝试创建一个将数据存储在本地缓冲区中并充当数据库接口(interface)的类。我有以下代码: class Table(object): def __init__(self, ta
我在第 3 方模块中找到了这段代码,在这种情况下,该模块忽略了 foo[::step] 或 key.step。 def __getitem__(self, key): if isinstanc
我正在运行 Python 2.7.10。 我需要拦截列表中的更改。 “更改”是指任何在浅层意义上修改列表的内容(如果列表由相同顺序的相同对象组成,则列表不会更改,而不管这些对象的状态如何;否则,它是)
我有以下字典: class Only5Items(dict): def __setitem__(self, key, value): if len(self) < 5:
这是我所做的,尝试为类似 dict 的数据库创建一个包装器,以及其他功能: class database(object): def __init__(self, name):
我不想在使用 __setitem__ 时测试键的类型。但奇怪的是,我发现使用多个键时,部分代码被省略了。这是我的测试类: class foo(): def __init__(self):
我有一个 list 的子类这在列表的组件上添加了一些管理内容。一切正常,但 mypy投诉 super 的签名调用 __setitem__ . 这是问题减少到最低限度: from typing impo
在下面的示例中,如果通过 = 设置数据,则有一个具有 __setitem__ 方法的类可以正常工作。但是,如果例如 list 类型的数据是使用 .append 方法隐式设置的,则不会调用 __seti
在下面的示例中,如果通过 = 设置数据,则有一个具有 __setitem__ 方法的类可以正常工作。但是,如果例如 list 类型的数据是使用 .append 方法隐式设置的,则不会调用 __seti
如果你这样做 import gdbm db = gdbm.open('foo', 'cs') 你得到一个对象: 您现在可以通过以下方式在数据库中设置键和值: db['foo'] = 'bar' pr
我有以下类(class): class autoArray2(numpy.ndarray): def __new__(self, *args, **kwargs): obj =
我有以下代码: class VectorN(object): def __init__(self, param): if isinstance(param, int):
我正在构建一个子类 dict 并覆盖 __setitem__ 的类。我想确定在所有可能设置字典项的情况下都会调用我的方法。 我发现了三种情况,Python(本例中为 2.6.4)在设置值时不调用我重写
我试图实现一个(原型(prototype),而不是生产)版本的持久字典,它使用磁盘上的pickle作为持久存储。但是,pickle.load 出于自身目的调用 __setitem__ ,并且(当然)会
基于Paul's answer ,我尝试运行以下冒泡排序算法,该算法使用 slice 和 __setitem__ 方法;我确信有一些简单的事情我做得不对,不确定那可能是什么? 代码 def bubbl
在下面的语句中定义一个类的行为: my_object[item] = ... 我知道我需要定义 __setitem__ 方法。 下面的语句需要定义什么方法: my_object[item] += ..
谁能告诉我为什么这段代码提示容器上没有 __setitem__?我以为我只需要容器上的 __getitem__ 来获取项目,然后 __iadd__ 来设置值,不知道为什么它期待 __setitem__
我正在开发一个自定义类来使用 Python 处理矩阵。我遇到了一个问题,我的测试程序显然没有向我的 __setitem__ 方法传递足够的参数。这是代码: def __setitem__(self,
var obj = {} obj.__setitem__ = function(key, value){ this[key] = value * value } obj.x = 2 // 4 o
我是一名优秀的程序员,十分优秀!