尝试在__getattr__中返回默认值时,Python泡菜崩溃 [英] Python pickle crash when trying to return default value in __getattr__

查看:99
本文介绍了尝试在__getattr__中返回默认值时,Python泡菜崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像类的字典,用于存储一些值作为属性.我最近添加了一些逻辑(__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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆