views:

590

answers:

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"
A: 

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()
Unknown
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
Not all callables that you find on a instance are methods. Example:x = SomeTest()x.lala = lambda arg : arg * 2
Daniel Ribeiro
@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
@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
Why not use the "callable" keyword instead of using the attribute?
Rohit
callable has been removed from Python 3.x, but hasattr works in both 2.x and 3.x
Anon
@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
@Anon, I have already proved him incorrect with a definition straight from the Python manual. That's why he deleted his own post.
Unknown
-1 for being a contrary nit-picker. Grow up.
Kieveli
@Kieveli, I am not the one being immature here. They are the ones who started it by downvoting me. Are you really going to try to police correct answers that defend themselves by downvoting? **You** should grow up.
Unknown
If you re-read both his comment, and the original question, you see that 'lambda callables' aren't strictly methods in an object, and Daniel is perfectly correct. Shame on you for bullying Daniel (apparently into deleting an answer). Shame on you for accusing them of being immature and following with "they started it". Shameful behaviour.
Kieveli
@Kieveli, no you are wrong. Shame on you for trying to shame the correct answer. You ever heard of monkey patching? "lambda callables" attached to an object are methods. If you want to argue with this, go argue with whoever wrote the Python manual. You are the one that is bullying me, at least Daniel had the good sense to self-delete when he realized that he was wrong. You could learn a little humility from that.
Unknown
A: 

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
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
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
(continued from previous comment) "When a user-defined method object is created by retrieving" and you will see what I am talking about.
Unknown
+1  A: 

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
A: 

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

modchan