为什么__setattr__()在设置成员数组变量元素时不递归?

Why does __setattr__() not recurse when setting member array variable elements?

不确定 SO 是否是正确的询问地点,但这里是...

我一直在学习 __setattr__() and __getattr__() 并且觉得我了解各种递归危险,除了 class 实例数组变量中的元素被设置时似乎没有在这种情况下递归。

class Test(object):
    tableInfo = { 'table1' : {'col1' : 0, 'col2':1} }

    def __init__(self, tableName):
        super(Test, self).__setattr__('_tableName', tableName) # Must be set this way to stop infinite recursion as attribute is accessed in bot set and get attr
        self._rowData = [123, 456]

    def __getattr__(self, name):
        print "# GETTING %s"  % (name)
        assert self._tableName in Test.tableInfo

        if name in Test.tableInfo[self._tableName]:
            return self._rowData[Test.tableInfo[self._tableName][name]]
        else:
            raise AttributeError()

    def __setattr__(self, name, val):
        print "# SETTING %s" % (name)
        if name in Test.tableInfo[self._tableName]:
            print "Table column name found"
            self._rowData[Test.tableInfo[self._tableName][name]] = val
            self._someAttr = 1
        else:
            super(Test, self).__setattr__(name, val)

class Table1(Test):
    def __init__(self, *args, **kwargs):
        super(Table1, self).__init__("table1", *args, **kwargs)

t = Table1()
print t.col1
print t.col2
t.col1 = 999
print t.col1

t.dummy = 101

我正在玩的例子粘贴在下面:

$ python test.py 
# SETTING _rowData
# GETTING col1
123
# GETTING col2
456
# SETTING col1
Table column name found
# SETTING _someAttr
# GETTING col1
999
# SETTING dummy

我可以看到设置 col1 导致递归回到 __setattr__(),正如我所期望的那样,由于行 self._someAttr = 1.

我不明白的是为什么我没有看到 self._rowData[Test.tableInfo[self._tableName][name]] = val.

行的类似递归原因

有人知道这是为什么吗?谢谢...

如果我没理解错的话,看看表达式本身应该可以回答你的问题:

self._rowData[bla] = val 被解析为

  • self.__getattribute__("_rowData")[bla] = val
  • 然后是self.__getattribute__("_rowData").__setitem__(bla, val)

没有进一步的 __setattr__ 调用,因为中间没有设置任何属性,您只需更改一个。