Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在这种情况下,为什么setattr和delattr会引发AttributeError?_Python_Attributes_Lookup_Python Descriptors_Python Datamodel - Fatal编程技术网

Python 在这种情况下,为什么setattr和delattr会引发AttributeError?

Python 在这种情况下,为什么setattr和delattr会引发AttributeError?,python,attributes,lookup,python-descriptors,python-datamodel,Python,Attributes,Lookup,Python Descriptors,Python Datamodel,在Python中,对象和类型的基本原理是什么?同样地,object.\uuuuu delattr\uuuuuu和type.\uuuuu delattr\uuuuuuu在属性删除过程中,如果类型具有作为数据描述符的属性而没有\uuu delete\uuuuuu方法,则该对象的基本原理是什么 我问这个问题是因为我注意到对象.\uuuuu getattribute\uuuuu和类型.\uuuuu getattribute\uuuuuu在属性查找过程中,如果类型有一个属性,而该属性是一个数据描述符,而没

在Python中,
对象和
类型的基本原理是什么?同样地,
object.\uuuuu delattr\uuuuuu
type.\uuuuu delattr\uuuuuuu
在属性删除过程中,如果类型具有作为数据描述符的属性而没有
\uuu delete\uuuuuu
方法,则该对象的基本原理是什么

我问这个问题是因为我注意到
对象.\uuuuu getattribute\uuuuu
类型.\uuuuu getattribute\uuuuuu
在属性查找过程中,如果类型有一个属性,而该属性是一个数据描述符,而没有
\uu get\uuuu
方法,则不会引发
属性错误

下面是一个简单的程序,它演示了通过
对象进行属性查找的区别。一方面(
AttributeError
未被提升),另一方面通过
对象进行属性更新。另一方面,通过
对象进行属性设置属性更新和属性删除(
AttributeError
被引发):

类数据描述符1:#缺少uu获取__
定义集(自身、实例、值):通过
定义删除(自身,实例):通过
类DataDescriptor2:#缺少u集__
def uu get uu(self,instance,owner=None):通过
定义删除(自身,实例):通过
类数据描述符3:#缺少uu删除__
def uu get uu(self,instance,owner=None):通过
定义集(自身、实例、值):通过
A类:
x=数据描述符1()
y=数据描述符2()
z=数据描述符3()
a=a()
vars(a).update({'x':'foo','y':'bar','z':'baz'})
a、 x
#实际值:返回“foo”
#预期:返回“foo”
a、 y='qux'
#实际值:引发AttributeError:\uu集__
#预期值:vars(a)['y']=='qux'
德尔阿兹
#实际:引发AttributeError:\u删除__
#应为:“z”不在变量(a)中
下面是另一个简单的程序,说明了按
类型查找属性和按
类型删除属性之间的区别(
AttributeError
被引发):

类数据描述符1:#缺少uu获取__
定义集(自身、实例、值):通过
定义删除(自身,实例):通过
类DataDescriptor2:#缺少u集__
def uu get uu(self,instance,owner=None):通过
定义删除(自身,实例):通过
类数据描述符3:#缺少uu删除__
def uu get uu(self,instance,owner=None):通过
定义集(自身、实例、值):通过
M类(类型):
x=数据描述符1()
y=数据描述符2()
z=数据描述符3()
A类(元类=M):
x='foo'
y=‘巴’
z='baz'
A.x
#实际值:返回“foo”
#预期:返回“foo”
A.y='qux'
#实际值:引发AttributeError:\uu集__
#预期值:vars(A)['y']=='qux'
德尔阿兹
#实际:引发AttributeError:\u删除__
#应为:“z”不在变量(A)中

对于属性更新和属性删除,我希望对实例字典进行变异,而不是获取
AttributeError
。属性查找从实例字典返回一个值,因此我想知道为什么属性更新和属性删除也不使用实例字典(就像如果类型没有数据描述符的属性一样)。

我认为这只是C级设计的结果,没有人真正考虑或关心它

在C级,
\uuuuu set\uuuuuuu
\uuuu delete\uuuuuuuuu
对应于相同的C级,
tp\u descr\u set
,通过向set传递空值来指定删除。(这类似于用于
\uuuuuu setattr\uuuuuuuu
\uuuuuuu delattr\uuuuuuuu
的设计,这也对应于通过
NULL
删除的设计。)

如果实现
\uuuu set\uuuuu
\uuu delete\uuuuu
,则C级插槽将设置为查找
\uuuu set\uuuu
\uuu delete\uuuuuu
并调用它:

static int
插槽描述集(PyObject*self、PyObject*target、PyObject*value)
{
PyObject*堆栈[3];
PyObject*res;
_Py_标识符(_删除__);
_Py_标识符(集合);
堆栈[0]=自身;
堆栈[1]=目标;
如果(值==NULL){
res=vectorcall\u方法(&PyId\uuuu\u delete\uuu,stack,2);
}
否则{
堆栈[2]=值;
res=向量调用方法(&PyId\uuuuuuuuuuuuuuuuuuuuu,堆栈,3);
}
如果(res==NULL)
返回-1;
Py_DECREF(res);
返回0;
}
插槽没有办法说“oops,没有找到方法,返回到正常处理”,它也没有尝试。它也没有尝试模拟正常处理-这很容易出错,因为“正常处理”依赖于类型,它不知道对所有类型模拟什么。如果插槽包装器找不到该方法,它只会引发异常


如果
\uuu set\uuu
\uu delete\uuuu
有两个插槽,这种效果就不会发生,但是在设计API时,有人会关心,我怀疑是否有人关心过。

正如您所建议的,基本问题似乎是,在查找
\uu set\uu
时,函数返回
-1
或者
\uuuu delete\uuuu
方法不存在,并且当查找的
\uuu set\uuuu
\uuuu delete\uuuu
方法存在时,但其调用会引发异常(通常是
AttributeError
)。因此调用函数无法进行区分,并在前一种情况下返回实例。