122

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
jmiserez
  • 2,991
  • 1
  • 23
  • 34
Rajeev
  • 44,985
  • 76
  • 186
  • 285

10 Answers10

147

Check if class has such method?

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

You can use self.__class__ instead of Dynamo

T.Todua
  • 53,146
  • 19
  • 236
  • 237
seriyPS
  • 6,817
  • 2
  • 25
  • 16
  • 27
    `None` is not callable, so you could just do `callable(getattr(Dynamo, 'mymethod', None))`. I used this answer because my super().mymethod() could throw `AttributeError` – sbutler Jul 26 '13 at 03:52
  • @sbutler Interesting that that works. According to PyCharm the signature for getattr is `def getattr(object, name, default=None):` I suspect that is not accurate because if it was I would expect passing None as the third parameter not to change the behaviour of the function. – maltem-za Nov 13 '13 at 10:28
  • 2
    @bszom: In a python shell, `help(getattr)` says "When a default argument is given, it is returned when the attribute doesn't exist; without it, an exception is raised in that case." -- (and indeed you can check that getattr does raise an exception if the attribute is missing) so clearly, whatever PyCharm is, it's wrong. – ShreevatsaR Jan 24 '14 at 19:12
  • @ShreevatsaR Thanks for confirming my suspicion. PyCharm is an IDE. – maltem-za Oct 22 '14 at 15:19
  • @bszom I found there is some discussion on this behavior of `getattr` here: http://stackoverflow.com/q/32499863/1545579 – Mahdi Nov 29 '16 at 09:14
  • 9
    **SIMPLER VERSION:** If you want to check if the current class INSTANCE has an attribute and it's callable, just do this: `if hasattr(self, "work") and callable(self.work)`. This checks if the instance has a work attribute (can be either a variable or a function), and then checks if it's callable (meaning it's a function). – Mitch McMabers Oct 13 '19 at 14:07
117

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?
John Strood
  • 1,859
  • 3
  • 26
  • 39
S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • 70
    But perhaps he really doesn't want to call it, just to check if there is that method (as it is in my case)... – Flavius Sep 08 '12 at 13:57
  • 62
    Note that this will fail if `dyn.mymethod()` raises an `AttributeError` itself. – D K Jan 03 '13 at 20:49
  • 1
    Unlike .NET, this is actually more performant than checking if the method exists. I'm surprised (in a good way). – ashes999 Nov 09 '13 at 04:38
  • 11
    as @DK says, this will trap any AttributeError that may be raised by the method being checked for, which may be undesirable (not to mention that it would wrongly infer the absence of the method in that case). – ShreevatsaR Jan 24 '14 at 16:46
  • @ashes999 could you please point out some official or well documented source proving that, please? – Rick77 Oct 09 '14 at 08:27
  • 1
    @Rick77 maybe my comment is poorly written. In .NET, exceptions are quite heavyweight and slow; a .NET developer would check if a method exists to avoid an exception. In Python, exceptions are quite light and fast. I don't have any documentation to prove it, sorry. – ashes999 Oct 09 '14 at 10:39
  • @Rick77 can you clarify what exactly you want to know? – ashes999 Oct 09 '14 at 13:47
  • 1
    I want to understand if using exceptions as lieu of testing is the correct approach in python (it isn't in most languages, which is why exceptions are called like that...). In your comment you wrote *this [calling the function and trapping exceptions, i presume] is actually more performant than checking if the method exists* , and I'd liked to know where you got that information, that's all... – Rick77 Oct 09 '14 at 14:20
  • 1
    @ashes999 aside from the fact of lightweight exceptions it's a bad sign — the check for a method existence shouldn't be longer than a simple check of a variable in memory, while exceptions *would include that check*, and over this do some other work *(like assembling a description)*. I guess that was some kind of a bug, and you shouldn't rely upon that kind of fastness. – Hi-Angel Aug 15 '15 at 23:29
  • 6
    Good in principle, and Python does have an "exceptions as control flow" culture unlike other languages. However, if you are using exception logging tools such as Sentry/Raven, or New Relic, such exceptions have to be filtered out individually (if that's possible) or generate noise. I would prefer to check if the method exists rather than calling it. – RichVel Jul 14 '16 at 08:30
  • 2
    The OP asked "How to check whether a method exists in Python?" not "How do I execute a method which might not exist?". You've answered a different question. – Mark Bolusmjak Nov 14 '17 at 20:55
  • This method will raise `TypeError` if the object will find the attribute `mymethod`, but it isn't callable. – User3759685 Jan 19 '18 at 11:41
  • 5
    This is wrong on so many levels. Method itself can raise AttributeError and this would be detected as method does not exist! It also ruins debugger support to break on exceptions. I'm also sure this probably impacts performance if thing was in loop. Last but not list I might not want to execute method, just validate if it exist. You should consider removing this answer or at least put all these warnings so naive folks don't get mislead. – Shital Shah Feb 12 '19 at 11:35
  • 100% agreed with @ShitalShah. Also, the method might be expecting some argument (perhaps specifically typed) which is not currently available (maybe I'm validating an user-supplied object before working with it) - what then? If it does and I blindly call it, I'll get a nice TypeError which goes uncaught. Yes, *easier to ask forgiveness than permission*, but *foolish consistency is the hobgoblin of little minds*. – Przemek D Sep 27 '19 at 12:44
107

How about dir() function before getattr()?

>>> "mymethod" in dir(dyn)
True
Michał Šrajer
  • 30,364
  • 7
  • 62
  • 85
29

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                                                          
Shital Shah
  • 63,284
  • 17
  • 238
  • 185
  • 3
    This answer is more suitable (in my opinion at least) than other answers because it does not use a general approach (using `try` statement) and it does check whenever the member is an actual function. great share! – ymz Oct 07 '19 at 07:41
19

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')
vint83
  • 191
  • 1
  • 2
  • +1 for pointing to the `inspect` module. However, *ismethod* will fail with methods from parent classes. Your object might have the default *\_\_repr__* from *object*, but it is not a method of your class. – Yaroslav Nikitenko Mar 27 '23 at 15:45
4

How about looking it up in dyn.__dict__?

try:
    method = dyn.__dict__['mymethod']
except KeyError:
    print "mymethod not in dyn"
deStrangis
  • 1,912
  • 1
  • 18
  • 25
  • underbar-prefixed methods by convention means 'private'. – xtofl Mar 22 '17 at 08:31
  • double-underbar prefix plus double-underbar suffix means 'this is normally used by the Python interpreter itself' and usually there is some way to do achive the same effect from a user's program for the most common use cases (in this case it would be using dot notation for an attribute), but it is neither forbidden nor wrong to use it if your use case really calls for it. – deStrangis May 12 '17 at 11:50
  • It is not forbidden. The wrongness is subjective: it depends on how much you want to confuse programmers that adhere to conventions: don't use it unless you have no alternative. – xtofl May 12 '17 at 12:10
3

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
Tonechas
  • 13,398
  • 16
  • 46
  • 80
3

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()

gerowam
  • 383
  • 1
  • 11
0

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
niek tuytel
  • 899
  • 7
  • 18
-1

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.

aweis
  • 5,350
  • 4
  • 30
  • 46