Rajeev
Rajeev

Reputation: 46919

How to check whether a method exists in Python?

In the function __getattr__(), if a referred variable is not found then it gives an error. How can I check to see if a variable or method exists as part of an object?

import string
import logging

class Dynamo:
 def __init__(self,x):
  print "In Init def"
  self.x=x
 def __repr__(self):
  print self.x
 def __str__(self):
  print self.x
 def __int__(self):
  print "In Init def"
 def __getattr__(self, key):
    print "In getattr"
    if key == 'color':
        return 'PapayaWhip'
    else:
        raise AttributeError


dyn = Dynamo('1')
print dyn.color
dyn.color = 'LemonChiffon'
print dyn.color
dyn.__int__()
dyn.mymethod() //How to check whether this exist or not

Upvotes: 133

Views: 150141

Answers (12)

YanSte
YanSte

Reputation: 10839

Here's a flexible solution:

def has_method_implementation(method: str, cls: type) -> bool:
    """
    Check if a method is implemented within a given class or its ancestors.

    Examples:
        Consider a class hierarchy where `BaseClass` defines a method `output` that raises
        `NotImplementedError`, and `SubClass` overrides `output` with its own implementation.

        ```python
        class Output:
            pass

        class BaseClass:
            def method(self, output: Any) -> Output:
                raise NotImplementedError()

        class SubClass(BaseClass):
            def method(self, output: Any) -> Output:
                # Implementation here
                return Output()

        # Check if `output` method is implemented in `BaseClass` and `SubClass`
        print(has_method_implementation('method', BaseClass))  # False
        print(has_method_implementation('method', SubClass))   # True

        # In your mother class, if the child has implemented the method.
        has_method_implementation('method', self.__class__) # True
        ```
    """
    # Get all the methods of the class
    for name, member in inspect.getmembers(cls, inspect.isfunction):
        if method == name and member.__qualname__.startswith(cls.__name__):
            return True
    else:
        return False

How to Use:

  • From within a class (e.g., mother class checking if child implements a method):

    # In your mother class, if the child has implemented the method.
    
    has_method_implementation('method_name', self.__class__)
    
  • Directly on a class:

    has_method_implementation('method_name', MyClass)
    

Replace 'method_name' with the actual method name you want to check.

This function checks if a method is implemented within a class (cls) by inspecting its methods.

Upvotes: 0

Muhammad Dyas Yaskur
Muhammad Dyas Yaskur

Reputation: 8098

I believe this approach also works and appears simpler to me.

class Dynamo:
    def __init__(self, x):
        pass
    def mymethod(self):
        pass

dyn = Dynamo('1')

if dyn.mymethod:
    print("mymethod is exist")
else:
    print("mymethod is not exist")

Just a note: it doesn't check whether it is callable or not, but it works if the method is unique and not duplicated with attributes or properties.

Upvotes: 0

seriyPS
seriyPS

Reputation: 7102

Check if class has such method?

hasattr(Dynamo, key) and callable(getattr(Dynamo, key))

You can use self.__class__ instead of Dynamo

Upvotes: 154

niek tuytel
niek tuytel

Reputation: 1179

For the people that likes simplicity.


class ClassName:
    def function_name(self):
        return

class_name = ClassName()
print(dir(class_name))
# ['__init__', .... ,'function_name']

answer = 'function_name' in dir(class_name)
print("is'function_name' in class ? >> {answer}")
# is 'function_name' in class ? >> True

Upvotes: 0

Shital Shah
Shital Shah

Reputation: 68738

I use below utility function. It works on lambda, class methods as well as instance methods.

Utility Method

def has_method(o, name):
    return callable(getattr(o, name, None))

Example Usage

Let's define test class

class MyTest:
  b = 'hello'
  f = lambda x: x

  @classmethod
  def fs():
    pass
  def fi(self):
    pass

Now you can try,

>>> a = MyTest()                                                    
>>> has_method(a, 'b')                                         
False                                                          
>>> has_method(a, 'f')                                         
True                                                           
>>> has_method(a, 'fs')                                        
True                                                           
>>> has_method(a, 'fi')                                        
True                                                           
>>> has_method(a, 'not_exist')                                       
False                                                          

Upvotes: 36

S.Lott
S.Lott

Reputation: 391854

It's easier to ask forgiveness than to ask permission.

Don't check to see if a method exists. Don't waste a single line of code on "checking"

try:
    dyn.mymethod() # How to check whether this exists or not
    # Method exists and was used.  
except AttributeError:
    # Method does not exist; What now?

Upvotes: 122

gerowam
gerowam

Reputation: 383

If your method is outside of a class and you don't want to run it and raise an exception if it doesn't exist:

'mymethod' in globals()

Upvotes: 3

user6559980
user6559980

Reputation: 41

Maybe like this, assuming all method is callable

app = App(root) # some object call app 
att = dir(app) #get attr of the object att  #['doc', 'init', 'module', 'button', 'hi_there', 'say_hi']

for i in att: 
    if callable(getattr(app, i)): 
        print 'callable:', i 
    else: 
        print 'not callable:', i

Upvotes: 4

vint83
vint83

Reputation: 191

You can try using 'inspect' module:

import inspect
def is_method(obj, name):
    return hasattr(obj, name) and inspect.ismethod(getattr(obj, name))

is_method(dyn, 'mymethod')

Upvotes: 19

aweis
aweis

Reputation: 5596

I think you should look at the inspect package. It allows you to 'wrap' some of the things. When you use the dir method it also list built in methods, inherited methods and all other attributes making collisions possible, e.g.:

class One(object):

    def f_one(self):
        return 'class one'

class Two(One):

    def f_two(self):
        return 'class two'

if __name__ == '__main__':
    print dir(Two)

The array you get from dir(Two) contains both f_one and f_two and a lot of built in stuff. With inspect you can do this:

class One(object):

    def f_one(self):
        return 'class one'

class Two(One):

    def f_two(self):
        return 'class two'

if __name__ == '__main__':
    import inspect

    def testForFunc(func_name):
        ## Only list attributes that are methods
        for name, _ in inspect.getmembers(Two, inspect.ismethod):
            if name == func_name:
                return True
        return False

    print testForFunc('f_two')

This examples still list both methods in the two classes but if you want to limit the inspection to only function in a specific class it requires a bit more work, but it is absolutely possible.

Upvotes: -1

deStrangis
deStrangis

Reputation: 1930

How about looking it up in dyn.__dict__?

try:
    method = dyn.__dict__['mymethod']
except KeyError:
    print "mymethod not in dyn"

Upvotes: 4

Michał Šrajer
Michał Šrajer

Reputation: 31182

How about dir() function before getattr()?

>>> "mymethod" in dir(dyn)
True

Upvotes: 112

Related Questions