Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to make a class work nicely with `hasattr` in `__getattr__` implementation?

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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 an AttributeError exception.

hasattr(object, name) … is implemented by calling getattr(object, name) and seeing whether it raises an AttributeError or 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.)

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading