构造方法中调用__setattr__或__getattr__ 方法造成的最大递归深度问题
Posted liuyinzhou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了构造方法中调用__setattr__或__getattr__ 方法造成的最大递归深度问题相关的知识,希望对你有一定的参考价值。
问题抛出
1 class Local(object): 2 """ 3 实现的功能: 4 不同的线程使用同一个变量,没有使用thread_local,但却做到了变量之间数据的独立性 5 """ 6 def __init__(self): 7 # 维护着创建的每个线程id和及其value 8 self.storage = {} 9 self.get_ident = get_ident 10 11 def __setattr__(self, key, value): 12 # 设置一次值就会获取当前线程id 13 ident = self.get_ident() 14 origin = self.storage.get(ident) 15 if not origin: 16 origin = {key:value} 17 origin[key] = value 18 self.storage[ident] = origin 19 20 def __getattr__(self, item): 21 # 获取当前线程id 22 ident = self.get_ident() 23 origin = self.storage.get(ident) 24 if not origin: 25 return None 26 return origin.get(item) 27 28 29 local_values = Local()
1 "D:Program FilesPython36python.exe" D:/Demo/s8/flaskdemo/threading_local.py 2 Traceback (most recent call last): 3 File "D:/Demo/s8/flaskdemo/threading_local.py", line 162, in <module> 4 local_values = Local() 5 File "D:/Demo/s8/flaskdemo/threading_local.py", line 141, in __init__ 6 self.storage = {} 7 File "D:/Demo/s8/flaskdemo/threading_local.py", line 146, in __setattr__ 8 ident = self.get_ident() 9 File "D:/Demo/s8/flaskdemo/threading_local.py", line 155, in __getattr__ 10 ident = self.get_ident() 11 File "D:/Demo/s8/flaskdemo/threading_local.py", line 155, in __getattr__ 12 ident = self.get_ident() 13 File "D:/Demo/s8/flaskdemo/threading_local.py", line 155, in __getattr__ 14 ident = self.get_ident() 15 [Previous line repeated 326 more times] 16 RecursionError: maximum recursion depth exceeded 17 18 Process finished with exit code 1
原因分析
类似的超过递归深度的示例还有:
解决方案
1 class Local(object): 2 """ 3 实现的功能: 4 不同的线程使用同一个变量,没有使用thread_local,但却做到了变量之间数据的独立性 5 """ 6 def __init__(self): 7 # 维护着创建的每个线程id和及其value 8 # self.storage = {} 9 # self.get_ident = get_ident 10 object.__setattr__(self, ‘storage‘, {}) 11 object.__setattr__(self, ‘ident_func‘, get_ident) 12 13 def __setattr__(self, key, value): 14 # 设置一次值就会获取当前线程id 15 ident = self.get_ident() 16 origin = self.storage.get(ident) 17 if not origin: 18 origin = {key:value} 19 origin[key] = value 20 self.storage[ident] = origin 21 22 def __getattr__(self, item): 23 # 获取当前线程id 24 ident = self.get_ident() 25 origin = self.storage.get(ident) 26 if not origin: 27 return None 28 return origin.get(item) 29 30 31 local_values = Local()
实现的原理:
在构造方法中不调用自身实例的__setattr__或者__getattr__,而调用object类的这两个方法即可避免最大递归深度的问题。
以上是关于构造方法中调用__setattr__或__getattr__ 方法造成的最大递归深度问题的主要内容,如果未能解决你的问题,请参考以下文章
python自定义属性访问__setattr__, __getattr__, __setattribute__
Python魔法方法(13):__setattr __(self, key, value) 方法
Python魔法方法(13):__setattr __(self, key, value) 方法
Python魔法方法(13):__setattr __(self, key, value) 方法
python 自定义属性访问 __setattr__, __getattr__,__getattribute__, __call__