- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个像这样将字典转换为对象的类
class Dict2obj(dict):
__getattr__= dict.__getitem__
def __init__(self, d):
self.update(**dict((k, self.parse(v))
for k, v in d.iteritems()))
@classmethod
def parse(cls, v):
if isinstance(v, dict):
return cls(v)
elif isinstance(v, list):
return [cls.parse(i) for i in v]
else:
return v
当我尝试对对象进行深度复制时出现此错误
import copy
my_object = Dict2obj(json_data)
copy_object = copy.deepcopy(my_object)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 172, in deepcopy
copier = getattr(x, "__deepcopy__", None)
KeyError: '__deepcopy__'
但是,如果我重写 Dict2obj
类中的 __getattr__
函数,我就能够进行深度复制操作。请参见下面的示例
class Dict2obj(dict):
__getattr__= dict.__getitem__
def __init__(self, d):
self.update(**dict((k, self.parse(v))
for k, v in d.iteritems()))
def __getattr__(self, key):
if key in self:
return self[key]
raise AttributeError
@classmethod
def parse(cls, v):
if isinstance(v, dict):
return cls(v)
elif isinstance(v, list):
return [cls.parse(i) for i in v]
else:
return v
为什么我需要覆盖 __getattr__
方法才能对此类返回的对象进行深层复制?
最佳答案
您的第一个类会出现此问题,因为 copy.deepcopy
尝试调用 getattr(x, "__deepcopy__", None)
.第三个参数的意义在于,如果对象的属性不存在,则返回第三个参数。
这在 the documentation for getattr()
中给出-
getattr(object, name[, default])
Return the value of the named attribute of object. name must be a string. If the string is the name of one of the object’s attributes, the result is the value of that attribute. For example, getattr(x, 'foobar') is equivalent to x.foobar. If the named attribute does not exist, default is returned if provided, otherwise AttributeError is raised.
如果基础 __getattr__
提高 AttributeError
和 default
为 getattr()
提供了参数函数调用 AttributeError
被 getattr()
捕获函数,它返回默认参数,否则它让 AttributeError
冒泡。示例 -
>>> class C:
... def __getattr__(self,k):
... raise AttributeError('asd')
...
>>>
>>> c = C()
>>> getattr(c,'a')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __getattr__
AttributeError: asd
>>> print(getattr(c,'a',None))
None
但在你的情况下,因为你直接分配 dict.__getitem__
至 __getattr__
,如果在字典中找不到该名称,则会引发 KeyError
,不是 AttributeError
因此它不会被 getattr()
处理和你的 copy.deepcopy()
失败。
您应该处理 KeyError
在你的getattr
然后提高 AttributeError
反而。示例 -
class Dict2obj(dict):
def __init__(self, d):
self.update(**dict((k, self.parse(v))
for k, v in d.iteritems()))
def __getattr__(self, name):
try:
return self[name]
except KeyError:
raise AttributeError(name)
...
关于python - 为什么在复制自定义对象时 deepcopy 失败并显示 "KeyError: ' __deepcopy_ _'"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33387801/
我有一个像这样将字典转换为对象的类 class Dict2obj(dict): __getattr__= dict.__getitem__ def __init__(self, d):
我是一名优秀的程序员,十分优秀!