Why does hasattr execute the @property decorator code block

Question:

In Python when I call the hasattr on a @property decorator the hasattr function actually runs the @property code block.

E.g. a class:

class GooglePlusUser(object):

    def __init__(self, master):
        self.master = master

    def get_user_id(self):
        return self.master.google_plus_service.people().get(userId='me').execute()['id']


    @property
    def profile(self):
        # this runs with hasattr
        return self.master.google_plus_service.people().get(userId='me').execute()

Running the following code calls the profile property and actually makes the call:

#Check if the call is an attribute
if not hasattr(google_plus_user, call):
    self.response.out.write('Unknown call')
    return

Why? How can I solve this without making the api call?

Asked By: Jimmy Kane

||

Answers:

hasattr() works by actually retrieving the attribute; if an exception is thrown hasattr() returns False. That’s because that is the only reliable way of knowing if an attribute exists, since there are so many dynamic ways to inject attributes on Python objects (__getattr__, __getattribute__, property objects, meta classes, etc.).

From the hasattr() documentation:

This is implemented by calling getattr(object, name) and seeing whether it raises an exception or not.

If you don’t want a property to be invoked when doing this, then don’t use hasattr. Use vars() (which returns the instance dictionary) or dir() (which gives you a list of names on the class as well). This won’t let you discover dynamic attributes handled by __getattr__ or __getattribute__ hooks however.

Answered By: Martijn Pieters

hasattr is basically implemented like this (except in C):

def hasattr(obj, attrname):
    try:
        getattr(obj, attname)
    except AttributeError:
        return False
    return True

So in true “easier to ask for forgiveness than permission” (EAFP) fashion, to find out if an object has a given attribute, Python simply tries to get the attribute, and converts failure to a return value of False. Since it’s really getting the attribute in the success case, hasattr() can trigger code for property and other descriptors.

To check for an attribute without triggering descriptors, you can write your own hasattr that traverses the object’s method resolution order and checks to see whether the name is in each class’s __dict__ (or __slots__). Since this isn’t attribute access, it won’t trigger properties.

Conveniently, Python already has a way to walk the method resolution order and gather the names of attributes from an instance’s classes: dir(). A simple way to write such a method, then, would be:

# gingerly test whether an attribute exists, avoiding triggering descriptor code
def gentle_hasattr(obj, name):
    return name in dir(obj) or hasattr(obj, name)

Note that we fall back to using hasattr() if we can’t find the desired name in dir(), because dir() won’t find dynamic attributes (i.e., where __getattr__ is overridden). Code for these will still be triggered, of course, so if you don’t care that you don’t find them, you could omit the or clause.

On balance, this is wasteful, since it gets all relevant attribute names when we’re interested only in whether a specific one exists, but it’ll do in a pinch. I’m not even sure that doing the loop yourself rather than calling dir() would be faster on average, since it’ll be in Python rather than in C.

Answered By: kindall

Making the variable as a class variable and then calling hasattr on it did the trick for me.

if not hasattr(google_plus_user, GooglePlusUser.call):
  self.response.out.write('Unknown call')
  return
Answered By: akansh tayal
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.