覆盖一个类实例的__getattr__方法?

时间:2015-11-18 23:52:18

标签: python getattr

我正在开展一个项目,处理抽象数学意义上的函数。如果没有让读者厌烦细节,我会说我在早期版本中有以下结构:

private static void ClearChunkVB(Vector2 PchunkXZ)
{
        VBContainer thisChunk;
        int j;

        thisChunk = Landscape.chunkVB[(int)PchunkXZ.X, (int)PchunkXZ.Y];

        if (thisChunk.voxelVB.Count > 0)
        {
            for (j = 0; j < thisChunk.voxelVB.Count; ++j)
            {
                thisChunk.voxelVB[j].VertCount = 0;
                VBPoolManager.DestroyVB(thisChunk.voxelVB[j]);
            }

            thisChunk.voxelVB.Clear();
        }
}

当然,这并不是我对class Foo(Bar): def __init__(self, a, b): self.a = a self.b = b self.sub_unit = Foo(a, not b) 的参数做出的改变,但足以说明,如果重复访问此属性,则必须导致{{无限长链'。 1}}对象。显然,当一个实例化Foo时,这会导致无限递归。我在早期版本中通过删除Foo的最后一行并将以下内容添加到Foo类来解决了这个问题:

init

这非常有效,因为我可以根据需要计算链中的下一个对象。

在查看代码时,我意识到由于其他原因,我需要Foo实例,而不是它的子类。要查看我是否可以覆盖单个实例的def __getattr__(self, attr: str): if attr == 'sub_unit': return Foo(self.a, not self.b) else: return super().__getattr__(attr) ,我尝试了以下内容:

Bar

这里发生了什么,我不明白?为什么getattr没有调用>>> foo = Bar(a=1, b=2) # sub_unit doesn't get set here. >>> foo.__getattr__ = lambda attr: 'foo' >>> foo.a 1 >>> foo.__getattr__('a') 'foo'

是否有一种方法可以为单个实例覆盖foo.a,或者我最好的选择是将我读取的所有代码foo.__getattr__('a')和朋友称为函数调用处理这个特例?

1 个答案:

答案 0 :(得分:1)

当您使用foo.a查找属性a时,python会在实例的属性字典中查找它。如果找不到,则会调用__getattr__方法。

相反,如果实例中存在a,则不会调用__getattr__