I have a class, where __getattr__ is implemented simply like:
def __getattr__(self, item): return self.__dict__[item]
The problem I’m seeing is that many Python libraries (e.g. numpy and pandas are trying to sniff whether my object has something called __array__ using this statement
hasattr(obj, '__array__`)
But my object is throwing an error at them saying there is no such attribute.
My dilemma: How can I make my class behave nicely with hasattr (by returning False) instead of throwing an error, WHILE at the same time, throw an error if any one wanted an attribute that doesn’t exist (i.e. I still want that error to be thrown in any other case).
EDIT: reproducible code as requested:
class A:
def __getattr__(self, item): return self.__dict__[item]
a = A()
hasattr(a, "lol")
traceback:
File "<ipython-input-31-b7d3ffac514f>", line 4, in <module>
hasattr(a, "lol")
File "<ipython-input-31-b7d3ffac514f>", line 2, in __getattr__
def __getattr__(self, item): return self.__dict__[item]
KeyError: 'lol'
>Solution :
From the docs:
__getattr__… should either return the attribute value or raise anAttributeErrorexception.
hasattr(object, name)… is implemented by callinggetattr(object, name)and seeing whether it raises anAttributeErroror not.
So you just need to raise an AttributeError:
class A:
def __getattr__(self, item):
try:
return self.__dict__[item]
except KeyError:
classname = type(self).__name__
msg = f'{classname!r} object has no attribute {item!r}'
raise AttributeError(msg)
a = A()
print(hasattr(a, "lol")) # -> False
print(a.lol) # -> AttributeError: 'A' object has no attribute 'lol'
(This error message is based on the one from object().lol.)