gpt4 book ai didi

python - 为什么没有 __getitem__ 引发 TypeError

转载 作者:太空狗 更新时间:2023-10-30 00:06:01 25 4
gpt4 key购买 nike

所以问题很简单:如果我们有一个随机类,比如说一个 int,我们尝试访问一个未定义的属性:

my_int = 5
my_int.this_is_a_test

我们会得到这个错误:

AttributeError: 'int' object has no attribute 'this_is_a_test'

但是如果我们尝试访问它的索引(在这种情况下,Python 将查找 __getitem__ 属性):

my_int = 5
my_int[0]

我们得到:

TypeError: 'int' object has no attribute '__getitem__'

异常类型变化背后的逻辑是什么?对我来说,引发 TypeError 似乎很奇怪,提示缺少属性(AttributeError 似乎是更好的选择)

最佳答案

这取决于你的意图。

In [1]: my_int = 5

In [2]: my_int.__getitem__(0) # -> AttributeError

In [3]: my_int[0] # -> TypeError

当您使用 . 时,您隐式调用了 getattr 函数,如果该属性不存在,它自然会引发 AttributeError

更新 2。让我们看看字节码。

In [11]: import dis

In [12]: def via_operator():
my_int = 5
my_int[0]


In [13]: def via_getattr():
my_int = 5
my_int.__getitem__(0)

In [14]: dis.dis(via_operator)
2 0 LOAD_CONST 1 (5)
3 STORE_FAST 0 (my_int)

3 6 LOAD_FAST 0 (my_int)
9 LOAD_CONST 2 (0)
12 BINARY_SUBSCR
13 POP_TOP
14 LOAD_CONST 0 (None)
17 RETURN_VALUE

In [15]: dis.dis(via_getattr)
2 0 LOAD_CONST 1 (5)
3 STORE_FAST 0 (my_int)

3 6 LOAD_FAST 0 (my_int)
9 LOAD_ATTR 0 (__getitem__)
12 LOAD_CONST 2 (0)
15 CALL_FUNCTION 1
18 POP_TOP
19 LOAD_CONST 0 (None)
22 RETURN_VALUE

如您所见,[] 有一个特殊的虚拟机指令。来自docs

BINARY_SUBSCR: Implements TOS = TOS1[TOS].

因此,当您未能执行一条指令时,引发 TypeError 是很自然的。

更新 1:查看 getattr 源代码,很明显这个函数永远不会引发这样的 TypeError,因此 [] 运算符不会在幕后调用它(至少对于内置类型而言,尽管最好找到来源来澄清这一点)。

static PyObject *
builtin_getattr(PyObject *self, PyObject *args)
{
PyObject *v, *result, *dflt = NULL;
PyObject *name;

if (!PyArg_UnpackTuple(args, "getattr", 2, 3, &v, &name, &dflt))
return NULL;
#ifdef Py_USING_UNICODE
if (PyUnicode_Check(name)) {
name = _PyUnicode_AsDefaultEncodedString(name, NULL);
if (name == NULL)
return NULL;
}
#endif

if (!PyString_Check(name)) {
PyErr_SetString(PyExc_TypeError,
"getattr(): attribute name must be string");
return NULL;
}
result = PyObject_GetAttr(v, name);
if (result == NULL && dflt != NULL &&
PyErr_ExceptionMatches(PyExc_AttributeError))
{
PyErr_Clear();
Py_INCREF(dflt);
result = dflt;
}
return result;
}

关于python - 为什么没有 __getitem__ 引发 TypeError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37123882/

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