4

What is the proper way to loop over a Python object's methods and call them?

Given the object:

class SomeTest():
  def something1(self):
    print "something 1"
  def something2(self):
    print "something 2"
Nicolas Dumazet
  • 7,147
  • 27
  • 36
BuddyJoe
  • 69,735
  • 114
  • 291
  • 466
  • 1
    Why aren't you using the unittest module, which does this for you? – S.Lott May 30 '09 at 13:14
  • 2
    trying to learn about Python introspection/reflection not Unit Testing. Although I realize that's what it looks like I am trying to do. – BuddyJoe May 30 '09 at 20:54

4 Answers4

10

You can use the inspect module to get class (or instance) members:

>>> class C(object):
...     a = 'blah'
...     def b(self):
...             pass
... 
...
>>> c = C()
>>> inspect.getmembers(c, inspect.ismethod)
[('b', <bound method C.b of <__main__.C object at 0x100498250>>)]

getmembers() returns a list of tuples, where each tuple is (name, member). The second argument to getmembers() is the predicate, which filters the return list (in this case, returning only method objects)

dcrosta
  • 26,009
  • 8
  • 71
  • 83
4

Methods vs. functions and other types of callables...

(To address the issue in the comments in Unknown's post.)

First, it should be noted that, in addition to user-defined methods, there are built-in methods, and a built-in method is, as the doc at http://docs.python.org/reference/datamodel.html says, "really a different disguise of a built-in function" (which is a wrapper around a C function.)

As for user-defined methods, as Unknown's cited quote says:

A user-defined method object combines a class, a class instance (or None) and any callable object (normally a user-defined function).

But this does not mean that "anything that defines __call__ and is attached to an object is a method." A method is a callable, but a callable is not necessarily a method. User-defined methods are wrappers around what the quote says.

Hopefully this output (from Python 2.5.2 which I have handy) will show the distinction:

IDLE 1.2.2      
>>> class A(object):
    x = 7


>>> A  # show the class object
<class '__main__.A'>
>>> a = A()
>>> a  # show the instance
<__main__.A object at 0x021AFBF0>
>>> def test_func(self):
    print self.x


>>> type(test_func)  # what type is it?
<type 'function'>
>>> dir(test_func)  # what does it have?
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__',
 '__getattribute__', '__hash__', '__init__', '__module__', '__name__',
 '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
 '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict',
 'func_doc', 'func_globals', 'func_name']
>>> # But now let's put test_func on the class...
>>> A.test = test_func
>>> type(A.test)  # What type does this show?
<type 'instancemethod'>
>>> dir(A.test)  # And what does it have?
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__get__',
 '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__',
 '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'im_class',
 'im_func', 'im_self']
>>> # See, we just got a wrapper, and the function is in 'im_func'...
>>> getattr(A.test, 'im_func')
<function test_func at 0x0219F4B0>
>>> # Now to show bound vs. unbound methods...
>>> getattr(a.test, 'im_self') # Accessing it via the instance
<__main__.A object at 0x021AFBF0>
>>> # The instance is itself 'im_self'
>>> a.test()
7
>>> getattr(A.test, 'im_self') # Accessing it via the class returns None...
>>> print getattr(A.test, 'im_self')
None
>>> # It's unbound when accessed that way, so there's no instance in there
>>> # Which is why the following fails...
>>> A.test()

Traceback (most recent call last):
  File "<pyshell#25>", line 1, in <module>
    A.test()
TypeError: unbound method test_func() must be called with A instance as
first argument (got nothing instead)
>>>

And - editing to add the following additional output, which is also relevant...

>>> class B(object):
    pass

>>> b = B()
>>> b.test = test_func  # Putting the function on the instance, not class
>>> type(b.test)
<type 'function'>
>>> 

I wont add more output, but you could also make a class an attribute of another class or instance, and, even though classes are callable, you would not get a method. Methods are implemented using non-data descriptors, so look up descriptors if you want more info on how they work.

Anon
  • 11,870
  • 3
  • 23
  • 19
  • Here the reasoning why this is wrong. Proposition 1: A user-defined method object combines a class, a class instance (or None) and any callable object. (defined by the Python Manual) Proposition 2: Every object that defines __call__ is a "callable object". (by simply defining call, you can execute any object like a function). Proposition 3: Thus, every object that defines __call__ and attached to an object is a "user-defined method". By definition, a "user-defined method" is a method. Therefore your quote about "a callable is not necessarily a method" when attached to an object is plain wrong. – Unknown Sep 12 '09 at 22:15
  • I'd also like to point out that its obvious there are distinctions between a normally defined method and a monkey patched method. However, this does not invalidate the fact that callables attached to an object are methods. It does not matter whether or not it is a specific type. It does not matter whether or not it is bound to a specific instance. In fact, the examples in your sadly wasted effort were already described in the manual you glossed over, except unlike you, it still refers to these things as methods.Take a look at the link again, and read the paragraph that starts with – Unknown Sep 12 '09 at 22:29
  • (continued from previous comment) "When a user-defined method object is created by retrieving" and you will see what I am talking about. – Unknown Sep 12 '09 at 22:30
0

This code snippet will call anything it will find in obj and store results in mapping, where key is attribute name — dict((k, v()) for (k, v) in obj.__dict__.iteritems() if k.startswith('something'))

toriningen
  • 7,196
  • 3
  • 46
  • 68
-1

Edit

Daniel, you are wrong.

http://docs.python.org/reference/datamodel.html

User-defined methods

A user-defined method object combines a class, a class instance (or None) and any callable object (normally a user-defined function).

Therefore, anything that defines __call__ and is attached to an object is a method.

Answer

The proper way to see what elements an object has is to use the dir() function.

Obviously this example only works for functions that take no arguments.

a=SomeTest()
for varname in dir(a):
    var = getattr(a, varname)
    if hasattr(var, "__call__"):
        var()
Community
  • 1
  • 1
Unknown
  • 45,913
  • 27
  • 138
  • 182
  • 2
    dir() might not be the best way possible of doing it, because dir() doesn't guarantee *every* member, it just says it will try to get the "interesting" ones. It's certainly a start, though. – Paul Fisher May 30 '09 at 04:51
  • Not all callables that you find on a instance are methods. Example: x = SomeTest() x.lala = lambda arg : arg * 2 – Daniel Ribeiro May 30 '09 at 05:03
  • @Paul, dir is supposed to be the way to do it. If you can't find it with dir, its not supposed to be found. – Unknown May 30 '09 at 05:24
  • @Daniel, your comment makes no sense. My method searches for the "__call__" variable, which is defined for lambdas and every other "callable" thing. If a callable thing is attached to an object, it is a method, no matter what type it really is. – Unknown May 30 '09 at 05:30
  • 1
    Why not use the "callable" keyword instead of using the attribute? – Rohit Jun 02 '09 at 03:41
  • 1
    callable has been removed from Python 3.x, but hasattr works in both 2.x and 3.x – Anon Jul 27 '09 at 14:06
  • @Unknown - Daniel is right. There is a difference between methods and functions and other callables. Search for info on bound and unbound methods (the latter of which are gone in 3.x). – Anon Jul 27 '09 at 14:33