I checked in some more changes (2.3 head only). This kind of program may be intractable: """ class C: def __getattr__(self, attribute): global alist if 'attr' in self.__dict__: alist.append(self.attr) del self.attr raise AttributeError import gc gc.collect() a = C() b = C() alist = [] a.attr = b b.attr = a a.x = 1 b.x = 2 del a, b # Oops. This prints 4: it's collecting # a, b, and their dicts. print gc.collect() # Despite that __getattr__ resurrected them. print alist # But gc cleared their dicts. print alist[0].__dict__ print alist[1].__dict__ # So a.x and b.x fail. print alist[0].x, alist[1].x """ While a __getattr__ side effect may resurrect an object in gc's unreachable list, gc has no way to know that an object has been resurrected short of starting over again. In the absence of that, the object remains in gc's unreachable list, and its tp_clear slot eventually gets called. The internal C stuff remains self-consistent, so this won't cause a segfault (etc), but it may (as above) be surprising. I don't see a sane way to fix this so long as asking whether __del__ exists can execute arbitrary mounds of Python code.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4