Hello everyone! In today’s article, we’ll take a look at how we can find all the methods of a given class.
Often, it is very convenient to list all the methods of a class directly, so that we can perform some pre-processing based on certain methods.
Let’s get started! We’ll show you some ways to make this happen, and you can use any one of the below methods.
Define our template class
Let’s first define a dummy class, from which we can verify our outputs.
Consider the below class, which has some methods:
class MyClass(object):
def __init__(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = a
def add(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = self.state + a
return self.state
def subtract(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = self.state - a
return self.state
def multiply(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = self.state * a
return self.state
def divide(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = self.state / a
return self.state
The class stores a floating point state
attribute, which we can manipulate using arithmetic operations.
Let’s now look at some of the ways to list the methods for our custom class.
Method 1 – Using the dir() function to list methods in a class
To list the methods for this class, one approach is to use the dir() function in Python.
The dir()
function will return all functions and properties of the class.
Let’s see what happens if we try it for MyClass
.
print(dir(MyClass))
Output
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'add',
'divide',
'multiply',
'subtract']
Ok, we can see that we have our add
, divide
, subtract
and multiply
methods listed! However, what about all the other methods?
Well, these methods (the ones starting with double underscore) are called dunder methods.
These are usually called by a wrapper function. For example, the dict()
function calls the __dict__()
method.
Filtering dunder methods from the output
Usually, we won’t be needing the double underscore prefixed methods, so we can filter them using the below snippet:
method_list = [method for method in dir(MyClass) if method.startswith('__') is False]
print(method_list)
Output
['add', 'divide', 'multiply', 'subtract']
Wow! We now only get the arithmetic methods that we wanted!
However, our present solution has a problem.
Remember that dir()
calls both the methods and the properties of a class?
Handling properties of a class
If we had property inside a class, it would list that too. Consider the below example.
class MyClass(object):
# MyClass property
property1 = [1, 2, 3]
def __init__(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = a
def add(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = self.state + a
return self.state
def subtract(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = self.state - a
return self.state
def multiply(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = self.state * a
return self.state
def divide(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = self.state / a
return self.state
@staticmethod
def global_method(a, b):
return a + b
@classmethod
def myclass_method(cls):
return cls
method_list = [method for method in dir(MyClass) if method.startswith('_') is False]
print(method_list)
Now, what do you think the output would be?
Output
['add', 'divide', 'global_method', 'multiply', 'myclass_method', 'property1', 'subtract']
This gives us property1
as well, which is not what we want.
We need to make one more filter to differentiate between a method and a property.
But this is really simple. The main difference is that any property object is NOT callable, while methods can be called!
In Python, we can use the boolean function callable(attribute)
to check if the attribute can be called.
Let’s now include this to our old code.
method_list = [attribute for attribute in dir(MyClass) if callable(getattr(MyClass, attribute)) and attribute.startswith('__') is False]
print(method_list)
Let’s break it down, by writing it without the list comprehension:
method_list = []
# attribute is a string representing the attribute name
for attribute in dir(MyClass):
# Get the attribute value
attribute_value = getattr(MyClass, attribute)
# Check that it is callable
if callable(attribute_value):
# Filter all dunder (__ prefix) methods
if attribute.startswith('__') == False:
method_list.append(attribute)
print(method_list)
We also changed method
to attribute
, so that it removes the misleading intention!
Let’s test it out now.
Output
['add', 'divide', 'global_method', 'multiply', 'myclass_method', 'subtract']
Indeed, we indeed get our method list, without the properties!
Method 2 – Using optparse.OptionParser
Now, this is another approach you can use, if you’re not too comfortable with using dir()
.
We can use the inspect
module to list the methods.
Namely, we can use inspect.getmembers(instance, predicate=inspect.ismethod)
to get a list of the methods.
This will automatically do the work for you, and you just need to deal with the output. Let’s look at an example.
import inspect
class MyClass(object):
# MyClass property
property1 = [1, 2, 3]
def __init__(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = a
def add(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = self.state + a
return self.state
def subtract(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = self.state - a
return self.state
def multiply(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = self.state * a
return self.state
def divide(self, a):
assert isinstance(a, float) or isinstance(a, int)
self.state = self.state / a
return self.state
@staticmethod
def global_method(a, b):
return a + b
@classmethod
def myclass_method(cls):
return cls
# Create our instance
instance = MyClass(100)
# Get the list of functions
method_list = inspect.getmembers(MyClass, predicate=inspect.ismethod)
print(method_list)
Output
[('__init__',
<bound method MyClass.__init__ of <__main__.MyClass object at 0x000001E55E36F390>>),
('add',
<bound method MyClass.add of <__main__.MyClass object at 0x000001E55E36F390>>),
('divide',
<bound method MyClass.divide of <__main__.MyClass object at 0x000001E55E36F390>>),
('multiply',
<bound method MyClass.multiply of <__main__.MyClass object at 0x000001E55E36F390>>),
('myclass_method',
<bound method MyClass.myclass_method of <class '__main__.MyClass'>>),
('subtract',
<bound method MyClass.subtract of <__main__.MyClass object at 0x000001E55E36F390>>)]
We can get the first element of each tuple, to get the method name.
Caveats of using the inspect module
Notice that we get a list of tuples. The first element of the tuple is the name of the function, which the second element represents the method object itself.
While this may seem to be a good solution, you may notice some things.
- For
dir()
, we directly used the Class name itself. But here, we need to pass an instance. - The staticmethods are also not shown in the list. Depending on your use case, you may/may not need it.
Due to the above mentioned points, I would suggest you to stay simple, and use the dir()
function!
Conclusion
In this article, we saw how we could list all the methods of a given class in Python.
References
- StackOverflow Question on listing all methods of a class