anonymous_1123581321
anonymous_1123581321

Reputation: 51

hasattr keeps returning False

class Avatar:

    def __init__(self, HP=100, damage=10, defends=10, magic=5):
        self.__hp = HP
        self.__dam = damage
        self.__def = defends
        self.__mag = magic

    def check_hasattr(self):
        print hasattr(Avatar,'__hp')

warrior = Avatar(99,9,9,4)
Avatar.check_hasattr(warrior)

Does somebody know why the print statement returns False while I expect True?

Upvotes: 5

Views: 2922

Answers (2)

bgusach
bgusach

Reputation: 15145

Your code does not work because you are checking that the class Avatar has the attribute __hp, which it does not have it, only instances have it, since that attribute is defined in __init__. In other words, the hasattr should be called on the self or avatar object, not on the Avatar class.

Moreover, double underscores have a special meaning in python, it mangles the name so that is "private" in the sense that cannot be accessed directly. This means that checking that the instance has the attribute __hp will not work (you should check _Avatar__hp instead)

I changed your code to simplify and remove things that do not make too much sense:

class Avatar:
    def __init__(self,HP=100):
        self._hp = HP

>>> avatar = Avatar()
>>> hasattr(avatar, '_hp')
True

Note: if you create an instance of Avatar avatar = Avatar(), you should be calling the methods directly on the object avatar.mymethod(), and not Avatar.mymethod(avatar)

Upvotes: 1

jonrsharpe
jonrsharpe

Reputation: 121966

You have two problems:

  1. Double underscore attribute names invoke "name mangling", so e.g. __hp becomes _Avatar__hp (see e.g. the style guide on inheritance).
  2. In check_hasattr you check for the attribute on Avatar, the class, rather than self, the instance.

This would work:

class Avatar:

    def __init__(self, HP=100, damage=10, defends=10, magic=5):
        self.__hp = HP
        self.__dam = damage
        self.__def = defends
        self.__mag = magic

    def check_hasattr(self):
        print hasattr(self, '_Avatar__hp')

However, there is no need to protect access to these attributes (and if there was, you should use a @property rather than name mangling); see e.g. Python name mangling

Note also that Class.method(instance) can be rewritten as instance.method(). In this case, though, the simplest approach would be to remove the method altogether and just call hasattr(warrior, '_Avatar__hp').

Upvotes: 10

Related Questions