一个类可以使用一些元魔法自己处理AttributeError吗?

时间:2016-07-23 17:30:09

标签: python

所以我有这个示例代码,其中Foo是非常动态的数据结构。

def fetch():
    # simulate api request
    return {'param1':1, 'param2':{'description':'param2', 'value':2}}

class Foo(object):
    def __init__(self):
        self._rawdata = fetch()     

        #set attributes accordingly to the downloaded data
        for key, val in self._rawdata.items():
            setattr(self, key, val)

    def __str__(self):
        # just an example
        out = ''
        for key, val in self._rawdata.items():
            out += key + ': ' + str(val) + '\n'
        return out

用户可能想尝试这样做:

f = Foo()
print(f.param3)

用户不知道' param3'是否存在(API可能没有任何数据可用,在这种情况下,它根本不会提供密钥) 当然,这会导致引发AttributeError。

    print(f.param3)
AttributeError: 'Foo' object has no attribute 'param3'

我的问题是:是否有一些元编程的神奇方法将Foo()类包装成一些能够使fn,fn.nonexistent_attribute'返回'无'而不是追溯?我真的想避免硬编码预期的属性(如果API改变了怎么办?)。

1 个答案:

答案 0 :(得分:3)

实施__getattr__ method;它将被调用所有不存在的属性:

def __getattr__(self, name):
    # all non-existing attributes produce None
    return None

来自文档:

  

当属性查找未在通常位置找到属性时调用(即,它不是实例属性,也不在self的类树中找到)。 name是属性名称。此方法应返回(计算的)属性值或引发AttributeError异常。

演示:

>>> def fetch():
...     # simulate api request
...     return {'param1':1, 'param2':{'description':'param2', 'value':2}}
...
>>> class Foo(object):
...     def __init__(self):
...         self._rawdata = fetch()
...         #set attributes accordingly to the downloaded data
...         for key, val in self._rawdata.items():
...             setattr(self, key, val)
...     def __getattr__(self, name):
...         # all non-existing attributes produce None
...         return None
...
>>> print(f.param1)
1
>>> f = Foo()
>>> print(f.param3)
None