title: Why is there a difference between inspect.ismethod and inspect.isfunction from python 2 -> 3?
body: <p>So this code:</p>
  
  <pre><code>from inspect import *
  
  class X(object):
    def y(self):
      pass
  
  methods = getmembers(X, predicate=ismethod)
  functions = getmembers(X, predicate=isfunction)
  
  print("%r" % methods)
  print("%r" % functions)
  </code></pre>
  
  <p>From python2.7 yields:</p>
  
  <pre><code>[('y', &lt;unbound method X.y&gt;)]
  []
  </code></pre>
  
  <p>and from python3.3 yields:</p>
  
  <pre><code>[]
  [('y', &lt;function X.y at 0x1006ee3b0&gt;)]
  </code></pre>
  
  <p>I've nosed around, but I can't see any obvious reason for this change in behavior. </p>
  
  <p>Specifically, why is python 3 treating my method as a function? </p>
  
  <p><strong>Is there any cross-runtime way of fetching the list of methods on a class?</strong></p>
  
  <p>(ie. something that returns the same when run on both python2.X and 3.X)</p>
  
  <p>Edit: Example of getmembers() not working:</p>
  
  <pre><code>from inspect import *
  
  class X(object):
    def y(self):
      pass
  
  methods = getmembers(X)
  for i in methods:
    if ismethod(i):
      print("Method: %s" % str(i))
    else:
      print("Not a method: %s" % str(i))
  </code></pre>
  
  <p>Prints:</p>
  
  <pre><code>Not a method: ('__class__', &lt;attribute '__class__' of 'object' objects&gt;)
  Not a method: ('__delattr__', &lt;slot wrapper '__delattr__' of 'object' objects&gt;)
  Not a method: ('__dict__', &lt;attribute '__dict__' of 'X' objects&gt;)
  Not a method: ('__dir__', &lt;method '__dir__' of 'object' objects&gt;)
  Not a method: ('__doc__', None)
  Not a method: ('__eq__', &lt;slot wrapper '__eq__' of 'object' objects&gt;)
  Not a method: ('__format__', &lt;method '__format__' of 'object' objects&gt;)
  Not a method: ('__ge__', &lt;slot wrapper '__ge__' of 'object' objects&gt;)
  Not a method: ('__getattribute__', &lt;slot wrapper '__getattribute__' of 'object' objects&gt;)
  Not a method: ('__gt__', &lt;slot wrapper '__gt__' of 'object' objects&gt;)
  Not a method: ('__hash__', &lt;slot wrapper '__hash__' of 'object' objects&gt;)
  Not a method: ('__init__', &lt;slot wrapper '__init__' of 'object' objects&gt;)
  Not a method: ('__le__', &lt;slot wrapper '__le__' of 'object' objects&gt;)
  Not a method: ('__lt__', &lt;slot wrapper '__lt__' of 'object' objects&gt;)
  Not a method: ('__module__', '__main__')
  Not a method: ('__ne__', &lt;slot wrapper '__ne__' of 'object' objects&gt;)
  Not a method: ('__new__', &lt;built-in method __new__ of type object at 0x1001e0640&gt;)
  Not a method: ('__reduce__', &lt;method '__reduce__' of 'object' objects&gt;)
  Not a method: ('__reduce_ex__', &lt;method '__reduce_ex__' of 'object' objects&gt;)
  Not a method: ('__repr__', &lt;slot wrapper '__repr__' of 'object' objects&gt;)
  Not a method: ('__setattr__', &lt;slot wrapper '__setattr__' of 'object' objects&gt;)
  Not a method: ('__sizeof__', &lt;method '__sizeof__' of 'object' objects&gt;)
  Not a method: ('__str__', &lt;slot wrapper '__str__' of 'object' objects&gt;)
  Not a method: ('__subclasshook__', &lt;method '__subclasshook__' of 'object' objects&gt;)
  Not a method: ('__weakref__', &lt;attribute '__weakref__' of 'X' objects&gt;)
  Not a method: ('y', &lt;function X.y at 0x1006ee3b0&gt;)
  </code></pre>