There are many `__special__` names that cause problems of this kind when you accidentally provide them by overriding `__getattr__`. I've found it best to always do
def __getattr__(self, name): if name.startswith('__'): raise AttributeError(name) ...
Actually, your custom getattr raises KeyError for missing attributes, which is a strange thing to get from an expression that looks like `obj.attrname`. I would suggest catching KeyError and raising AttributeError. This would actually have avoided your original `__deepcopy__` error too.
(Note: I've replaced initial spaces with non-breaking spaces so this blog won't mangle the indentation. If you actually copy & paste this code, expect interesting SyntaxErrors ;)
Comment
There are many `__special__` names that cause problems of this kind when you accidentally provide them by overriding `__getattr__`. I've found it best to always do
def __getattr__(self, name):
if name.startswith('__'):
raise AttributeError(name)
...
Actually, your custom getattr raises KeyError for missing attributes, which is a strange thing to get from an expression that looks like `obj.attrname`. I would suggest catching KeyError and raising AttributeError. This would actually have avoided your original `__deepcopy__` error too.
(Note: I've replaced initial spaces with non-breaking spaces so this blog won't mangle the indentation. If you actually copy & paste this code, expect interesting SyntaxErrors ;)
Replies
Excellent! Thanks!