尝试在__getattr__中返回默认值时,Python泡菜崩溃 [英] Python pickle crash when trying to return default value in __getattr__
问题描述
我有一个像类的字典,用于存储一些值作为属性.我最近添加了一些逻辑(__getattr__
)以在属性不存在时返回None.我做完这个泡菜后就崩溃了,我想知道为什么吗?
I have a dictionary like class that I use to store some values as attributes. I recently added some logic(__getattr__
) to return None if an attribute doesn't exist. As soon as I did this pickle crashed, and I wanted some insight into why?
测试代码:
import cPickle
class DictionaryLike(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __iter__(self):
return iter(self.__dict__)
def __getitem__(self, key):
if(self.__dict__.has_key(key)):
return self.__dict__[key]
else:
return None
''' This is the culprit...'''
def __getattr__(self, key):
print 'Retreiving Value ' , key
return self.__getitem__(key)
class SomeClass(object):
def __init__(self, kwargs={}):
self.args = DictionaryLike(**kwargs)
someClass = SomeClass()
content = cPickle.dumps(someClass,-1)
print content
结果:
Result:
Retreiving Value __getnewargs__
Traceback (most recent call last):
File <<file>> line 29, in <module>
content = cPickle.dumps(someClass,-1)
TypeError: 'NoneType' object is not callable`
我做蠢事吗?我读过一篇文章,如果键不存在,则deepcopy()可能要求我抛出异常?如果是这种情况,有什么简单的方法可以在不引发异常的情况下实现我想要的?
Did I do something stupid? I had read a post that deepcopy() might require that I throw an exception if a key doesn't exist? If this is the case is there any easy way to achieve what I want without throwing an exception?
最终结果是,如果有人打电话
End result is that if some calls
someClass.args.i_dont_exist
我希望它不返回任何值.
I want it to return None.
推荐答案
实现__getattr__
有点棘手,因为它会为每个不存在的属性调用.在您的情况下,pickle
模块将针对您的类测试 __getnewargs__
特殊方法并接收None
,这显然是不可调用的.
Implementing __getattr__
is a bit tricky, since it is called for every non-existing attribute. In your case, the pickle
module tests your class for the __getnewargs__
special method and receives None
, which is obviously not callable.
您可能需要更改__getattr__
来调用魔术名称的基本实现:
You might want to alter __getattr__
to call the base implementation for magic names:
def __getattr__(self, key):
if key.startswith('__') and key.endswith('__'):
return super(DictionaryLike, self).__getattr__(key)
return self.__getitem__(key)
我通常用下划线开头所有名称,以便避开内部符号的魔力.
I usually pass through all names starting with an underscore, so that I can sidestep the magic for internal symbols.
这篇关于尝试在__getattr__中返回默认值时,Python泡菜崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!