分配给属性引用期间出现 TypeError?
TypeError during assignment to attribute reference?
在 Python 的文档中阅读有关 Assignment statements 的内容,我发现了这个:
If the target is an attribute reference: The primary expression in the reference is evaluated. It should yield an object with assignable attributes; if this is not the case, TypeError
is raised. That object is then asked to assign the assigned object to the given attribute; if it cannot perform the assignment, it raises an exception (usually but not necessarily AttributeError
).
我想知道如何获得这个TypeError
?
什么Python类型没有设置属性的套路?
如果您想在代码中引发 TypeError:
raise TypeError
我建议您阅读 Python 中的异常和异常处理以获取更多信息。 https://docs.python.org/3/tutorial/errors.html
这个文档行真的已经过时了。它至少可以追溯到 Python 1.4,远早于 type/class 统一。我相信那时,尝试做一些像
x = 1
x.foo = 3
会产生 TypeError,但我当时并没有写 Python,而且我没有足够古老的解释器版本来测试它。
如果您查看 source code 属性分配分派,您可以看到记录的检查仍然存在:
if (tp->tp_setattro != NULL) {
...
return ...;
}
if (tp->tp_setattr != NULL) {
...
return ...;
}
Py_DECREF(name);
assert(name->ob_refcnt >= 1);
if (tp->tp_getattr == NULL && tp->tp_getattro == NULL)
PyErr_Format(PyExc_TypeError,
"'%.100s' object has no attributes "
"(%s .%U)",
tp->tp_name,
value==NULL ? "del" : "assign to",
name);
else
PyErr_Format(PyExc_TypeError,
"'%.100s' object has only read-only attributes "
"(%s .%U)",
tp->tp_name,
value==NULL ? "del" : "assign to",
name);
return -1;
如果对象的类型没有设置属性的例程,Python 会引发错误,根据该类型是否有获取属性的例程来抱怨 "no attributes" 或 "only read-only attributes"。我相信在早期,像 int
这样的类型会沿用这条代码路径。但是,现在所有类型都从 object
继承了此类例程,因此我认为此代码路径从未被采用。
type.__setattr__
中有一个相关的代码路径,它引发了一个 TypeError
用于设置用 C 编写的类型的属性。仍然采用此代码路径,但它不像文档描述的那样通用:
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
PyErr_Format(
PyExc_TypeError,
"can't set attributes of built-in/extension type '%s'",
type->tp_name);
return -1;
}
此代码生成一个 TypeError
,它似乎是文档描述的内容:
>>> def f(): pass
...
>>> f.func_globals = 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: readonly attribute
但是这个 TypeError
真的是因为文档这么说而引发的吗?我真心怀疑。我想 func_globals
实现只会引发 TypeError
如果你试图给它分配一些东西。
顺便说一句...
我实际上会在下一个示例中期望相同,但它是 AttributeError
:
>>> class A(object):
... __slots__ = 'a',
...
>>> A().b = 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'b'
更新 (Python 3)
以上内容在 Python 2.7 中。 Python 3中没有func_globals
,所以这个不适用(你可以给它赋值)。
Python 3 中的函数在只读时似乎会引发 AttributeError
。
>>> f.__globals__ = 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: readonly attribute
这对我来说非常有意义。就 Python 3 而言,这部分文档可能只是遗留物。
在 Python 的文档中阅读有关 Assignment statements 的内容,我发现了这个:
If the target is an attribute reference: The primary expression in the reference is evaluated. It should yield an object with assignable attributes; if this is not the case,
TypeError
is raised. That object is then asked to assign the assigned object to the given attribute; if it cannot perform the assignment, it raises an exception (usually but not necessarilyAttributeError
).
我想知道如何获得这个TypeError
?
什么Python类型没有设置属性的套路?
如果您想在代码中引发 TypeError:
raise TypeError
我建议您阅读 Python 中的异常和异常处理以获取更多信息。 https://docs.python.org/3/tutorial/errors.html
这个文档行真的已经过时了。它至少可以追溯到 Python 1.4,远早于 type/class 统一。我相信那时,尝试做一些像
x = 1
x.foo = 3
会产生 TypeError,但我当时并没有写 Python,而且我没有足够古老的解释器版本来测试它。
如果您查看 source code 属性分配分派,您可以看到记录的检查仍然存在:
if (tp->tp_setattro != NULL) {
...
return ...;
}
if (tp->tp_setattr != NULL) {
...
return ...;
}
Py_DECREF(name);
assert(name->ob_refcnt >= 1);
if (tp->tp_getattr == NULL && tp->tp_getattro == NULL)
PyErr_Format(PyExc_TypeError,
"'%.100s' object has no attributes "
"(%s .%U)",
tp->tp_name,
value==NULL ? "del" : "assign to",
name);
else
PyErr_Format(PyExc_TypeError,
"'%.100s' object has only read-only attributes "
"(%s .%U)",
tp->tp_name,
value==NULL ? "del" : "assign to",
name);
return -1;
如果对象的类型没有设置属性的例程,Python 会引发错误,根据该类型是否有获取属性的例程来抱怨 "no attributes" 或 "only read-only attributes"。我相信在早期,像 int
这样的类型会沿用这条代码路径。但是,现在所有类型都从 object
继承了此类例程,因此我认为此代码路径从未被采用。
type.__setattr__
中有一个相关的代码路径,它引发了一个 TypeError
用于设置用 C 编写的类型的属性。仍然采用此代码路径,但它不像文档描述的那样通用:
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
PyErr_Format(
PyExc_TypeError,
"can't set attributes of built-in/extension type '%s'",
type->tp_name);
return -1;
}
此代码生成一个 TypeError
,它似乎是文档描述的内容:
>>> def f(): pass
...
>>> f.func_globals = 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: readonly attribute
但是这个 TypeError
真的是因为文档这么说而引发的吗?我真心怀疑。我想 func_globals
实现只会引发 TypeError
如果你试图给它分配一些东西。
顺便说一句...
我实际上会在下一个示例中期望相同,但它是 AttributeError
:
>>> class A(object):
... __slots__ = 'a',
...
>>> A().b = 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'b'
更新 (Python 3)
以上内容在 Python 2.7 中。 Python 3中没有func_globals
,所以这个不适用(你可以给它赋值)。
Python 3 中的函数在只读时似乎会引发 AttributeError
。
>>> f.__globals__ = 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: readonly attribute
这对我来说非常有意义。就 Python 3 而言,这部分文档可能只是遗留物。