4

As some good people showed me that callable() can be used to solve this problem, I still found it to be a different question, because anyone that has this question in mind will not found the answer because he won't connect this directly to callable(). Plus I found a possible way to go around without using callable(), which is to use type() as showed in one of the answers from myself.

Assume I create a simple class as Cls

class Cls():
    attr1 = 'attr1'

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

    def meth1(self, num):
        return num**2

obj = Cls('attribute2')
print(hasattr(obj, 'attr1'))  # >>> True
print(hasattr(obj, 'attr2'))  # >>> True
print(hasattr(obj, 'meth1'))  # >>> True

From what I learned, an attribute is a variable inside a class, and a method is a function inside a class. They are not the same.

Apparently, there is no hasmethod() to be called by python. And it seems that hasattr() really gives all True to my test on 'attr1', 'attr2', 'meth1'. It does not differentiate from an attribute or a method.

And if I use dir(), the attributes and methods will all show up in the output, and you can't really tell which one is what type either.

Can someone please explain me why?

jxie0755
  • 1,682
  • 1
  • 16
  • 35
  • Possible duplicate of [What is a "callable" in Python?](https://stackoverflow.com/questions/111234/what-is-a-callable-in-python) – Stephen Rauch Jan 03 '18 at 03:44
  • In the Custom classes and Class instances *sections* of [The Standard Type Hierarchy](https://docs.python.org/3/reference/datamodel.html) , methods and functions are referred to as class attributes also. – wwii Jan 03 '18 at 03:51
  • https://docs.python.org/3/glossary.html#term-attribute – wwii Jan 03 '18 at 03:59

3 Answers3

5

No matter it's a variable or a method, they are all considered "attributes". So hasattr returns True.

The way in which methods are different is that they are callable. This can be checked by calling callable. So if you want to figure out whether an attribute is callable, you can

if hasattr(obj, "attr1"):
    if callable(obj.attr1):
        # attr1 is a method!
    else:
         # attr1 is not a method but an attribute
else:
    # attr1 is not an attribute
Sweeper
  • 213,210
  • 22
  • 193
  • 313
1

You can define hasmethod() as below

def hasmethod(obj,method_name):
     return hasattr(obj,method_name) and callable(getattr(obj,method_name))

print(hasmethod(obj,'meth1')) #True
print(hasmethod(obj,'attr1')) #False 
Abhijith Asokan
  • 1,865
  • 10
  • 14
0

Something interesting that I found is that if I call type() on the attributes, a method will shows up as a method, while attributes will be a string or an int or any other types.

print(type(obj.attr1))  # >>> <class 'str'>
print(type(obj.attr2))  # >>> <class 'str'>
print(type(obj.meth1))  # >>> <class 'method'>

maybe this can tell whether it is a method or not?

jxie0755
  • 1,682
  • 1
  • 16
  • 35