为什么__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__
调用,因为中间没有设置任何属性,您只需更改一个。
不确定 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__
调用,因为中间没有设置任何属性,您只需更改一个。