hasattr on class names
Asked Answered
P

3

5

hasattr documentation says that it takes an object and an attribute name and lets you know if that attribute exists on that object.

I have discovered that it seems to work on class names too (i.e. not an instance object).

Something like:

class A:
    def Attr1(self):
        pass

> hasattr(A, 'Attr1')
True
> 

I would like to use this to make some test code easier to write, but don't want to be bitten later in case this is a side effect of the implementation and not really intended.

Please don't ask to see the test code to see if I can do something else, as that is not really the question.

Is there any official python stance on this? I presume the object referred to, in the documentation is talking about an instance object.

I tried googling (and looking at some questions in StackOverflow), but didn't seem to find anything.

Pepin answered 27/4, 2015 at 16:5 Comment(12)
"I presume the object referred to, in the documentation is talking about an instance object" - no, any object, including the class itself.Precontract
That's normal. Remember that instance.method(stuff ...) is in fact syntactic sugar for Class.method(instance, stuff ...), i.e. those methods are in fact attributes of the class.Tennessee
@jonrsharpe: That is great! Is there any reference for that. Seems a bit strange to me :-)Pepin
@ProgrammerPerson if the documentation meant a specific kind of object, it would say that. Everything in Python is an object; you can run hasattr on anything.Precontract
@tobias_k: I understand that methods are attributes. What I am worried about is using hasattr(A, blah), instead of hasattr(x, blah) where x = A().Pepin
Classes are instance objects; they are instances of type (or whatever the metaclass of the class is).Amidst
@jonrsharpe: I am not disputing :-). Just want a reference (even for the sentence that everything is an object...) Asyou can tell, I am new to python...Pepin
@ProgrammerPerson oh, come on; first Google hit for "python everything is an object": https://mcmap.net/q/37361/-is-everything-an-object-in-python-like-ruby/3001761Precontract
@jonrsharpe: Come on :-). Everything is an object has multiple interpretations. Like 5 is an object. Do you include: Type T is an object? chepner's comment comes close to an answer for that.Pepin
btw, thanks everyone! I will wait a few hours before accepting an answer.Pepin
@ProgrammerPerson there's no "interpretation" here. 5 is an int object. int is a type object. Functions, classes, modules; all are objects of various kinds. Python is wholly object-oriented, it doesn't have the "primitive" data types of e.g. Java.Precontract
@jonrsharpe: There is, for someone new to python coming from other languages. Hence the confusion. I can understand saying every thing that can be passed around (including functions) are objects. But class names could still be considered non-objects. Anyway, seems like my question has been answered.Pepin
F
7

The fact that it works on a class in addition to an instance is intentional. In fact, hasattr should work on any object that you pass to it. Basically, it does something like this:

def hasattr(obj, attribute):
    try:
        getattr(obj, attribute)
    except:
        return False
    return True

You can rely on that and not be afraid of getting bit by a change later. Note, there is some discussion on python-dev about hasattr being broken by design. The gist of it is that hasattr catches any exception which can be misleading.


Note that, in python classes are themselves instances of type.

>>> class Foo(object):
...   pass
... 
>>> type(Foo)
<type 'type'>

so everything is an instance of something1.

1type is an instance of itself which is something that would be impossible to do in pure python...

Folio answered 27/4, 2015 at 16:10 Comment(4)
Interesting. I didn't realize hasattr() was broken like that.Morphology
@Morphology -- Yep. I've even seen people mention that it'll catch crazy stuff like StopIteration and SystemExit -- But I'm not sure if that's true. In any event, I've seen a number of people writing their own versions... return getattr(obj, attr, sentinel) is not sentinelFolio
I just looked into this and it's apparently fixed in 3.2... no word on whether 2.7 users are out of luck.Morphology
Your second paragraph answers it for me.Pepin
T
3

I do not have a reference on the "official Python stance" at hand, but this is perfectly normal and intentional. Remember that

instance_of_SomeClass.some_method(parameters, ...)

is in fact syntactic sugar for

SomeClass.some_method(instance_of_SomeClass, parameters, ...)

i.e. those methods are in fact attributes of the class and thus can be tested with hasattr.

Tennessee answered 27/4, 2015 at 16:13 Comment(1)
Good explanation. Gives the answer as to why methods are attributes of a class. That is, class attributes.Torsibility
C
1

Just want a reference (even for the sentence that everything is an object...)

I recommend you to read this chapter (or the whole book if you have the time):

http://www.diveintopython.net/getting_to_know_python/everything_is_an_object.html

Chemulpo answered 27/4, 2015 at 16:17 Comment(1)
Thanks for the link. I got +15 rep, so +1 for you :)Pepin

© 2022 - 2024 — McMap. All rights reserved.