0

在python中,当一个对象的类定义一个对象时,它是可下标的

__getitem__(self, k)

方法,允许我们通过括号语法“获取项目”:

obj[k]

内置 del 函数的语法是:

del(obj[k])

这会从(可下标的)对象 obj 中删除项目 k。但显然,没有调用特殊的 getitem 方法。

请参阅下面的示例

>>> class A:
...     def __init__(self, d):
...         self._d = d
...
...     def __getitem__(self, k):
...         print("Calling __getitem__")
...         return self._d[k]
...
...     def __delitem__(self, k):
...         del(self._d[k])
...
>>>
>>> a = A({1: 'one', 2: 'two', 3: 'three'})
>>> a._d
{1: 'one', 2: 'two', 3: 'three'}
>>> a[2]
Calling __getitem__
'two'
>>> del(a[2])
>>> # Note there was no "Calling __getitem__" print!

所以似乎在 a[2] 将工作转发给 getitem 方法之前,解释器知道 del 上下文,并绕过它,直接调用

a.__delitem__(2)

反而。

这是如何运作的?

最重要的是:这种机制是可定制的吗?

例如,我可以编写一个函数 foo 以便

foo(obj[k])

从不打电话

obj.__getitem__(k)

但是,例如,

obj.foo(k)
4

2 回答 2

2

del不是函数。它可以做到这一点,因为它不是一个函数。这就是为什么它不是一个函数。它是语言中内置的关键字,作为del语句的一部分。

要记住类似delreturn不是函数的东西(并避免意外的优先级意外),最好不要在“参数”周围加上括号:

del whatever

而不是

del(whatever)

del不获取对象并将其删除。右边的东西del不是要评估的表达式。它是一个target_list= ,与赋值语句左侧出现的语法相同:

target_list     ::=  target ("," target)* [","]
target          ::=  identifier
                     | "(" [target_list] ")"
                     | "[" [target_list] "]"
                     | attributeref
                     | subscription
                     | slicing
                     | "*" target

要删除订阅目标,如obj[k],Python 计算表达式obj和表达式k以生成两个对象,然后__delitem__以第二个对象作为参数调用第一个对象的方法。obj[k]永远不会被评估为表达式,尽管它的一部分是。


这一切都依赖于编译器和语法支持,不能用于任意用户定义的函数。

于 2019-03-21T17:35:39.247 回答
1

您正在编写示例代码,就好像del一个函数接受参数并假设a[2]必须首先通过 __getitem__(). 但严格来说,del是一种说法。这意味着语言解析器可以以特殊的方式处理它——换句话说,不一定像函数调用一样。

我们可以使用dis包来获得一些提示。请注意del 操作如何直接表示为非常具体的DELETE_SUBSCR操作。它绕过BINARY_SUBSCR了示例使用的步骤len

from dis import dis

def f(xs):
    del xs[2]

def g(xs):
    len(xs[2])

print('\n# del')
dis(f)
print('\n# len')
dis(g)

输出(总结):

# del
0 LOAD_FAST                0 (xs)
2 LOAD_CONST               1 (2)
4 DELETE_SUBSCR
6 LOAD_CONST               0 (None)
8 RETURN_VALUE

# len
 0 LOAD_GLOBAL              0 (len)
 2 LOAD_FAST                0 (xs)
 4 LOAD_CONST               1 (2)
 6 BINARY_SUBSCR
 8 CALL_FUNCTION            1
10 POP_TOP
12 LOAD_CONST               0 (None)
14 RETURN_VALUE
于 2019-03-21T17:49:06.780 回答