Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is there a difference between inspect.ismethod and inspect.isfunction from python 2 -> 3?

Tags:

So this 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)

From python2.7 yields:

[('y', <unbound method X.y>)]
[]

and from python3.3 yields:

[]
[('y', <function X.y at 0x1006ee3b0>)]

I've nosed around, but I can't see any obvious reason for this change in behavior.

Specifically, why is python 3 treating my method as a function?

Is there any cross-runtime way of fetching the list of methods on a class?

(ie. something that returns the same when run on both python2.X and 3.X)

Edit: Example of getmembers() not working:

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

Prints:

Not a method: ('__class__', <attribute '__class__' of 'object' objects>)
Not a method: ('__delattr__', <slot wrapper '__delattr__' of 'object' objects>)
Not a method: ('__dict__', <attribute '__dict__' of 'X' objects>)
Not a method: ('__dir__', <method '__dir__' of 'object' objects>)
Not a method: ('__doc__', None)
Not a method: ('__eq__', <slot wrapper '__eq__' of 'object' objects>)
Not a method: ('__format__', <method '__format__' of 'object' objects>)
Not a method: ('__ge__', <slot wrapper '__ge__' of 'object' objects>)
Not a method: ('__getattribute__', <slot wrapper '__getattribute__' of 'object' objects>)
Not a method: ('__gt__', <slot wrapper '__gt__' of 'object' objects>)
Not a method: ('__hash__', <slot wrapper '__hash__' of 'object' objects>)
Not a method: ('__init__', <slot wrapper '__init__' of 'object' objects>)
Not a method: ('__le__', <slot wrapper '__le__' of 'object' objects>)
Not a method: ('__lt__', <slot wrapper '__lt__' of 'object' objects>)
Not a method: ('__module__', '__main__')
Not a method: ('__ne__', <slot wrapper '__ne__' of 'object' objects>)
Not a method: ('__new__', <built-in method __new__ of type object at 0x1001e0640>)
Not a method: ('__reduce__', <method '__reduce__' of 'object' objects>)
Not a method: ('__reduce_ex__', <method '__reduce_ex__' of 'object' objects>)
Not a method: ('__repr__', <slot wrapper '__repr__' of 'object' objects>)
Not a method: ('__setattr__', <slot wrapper '__setattr__' of 'object' objects>)
Not a method: ('__sizeof__', <method '__sizeof__' of 'object' objects>)
Not a method: ('__str__', <slot wrapper '__str__' of 'object' objects>)
Not a method: ('__subclasshook__', <method '__subclasshook__' of 'object' objects>)
Not a method: ('__weakref__', <attribute '__weakref__' of 'X' objects>)
Not a method: ('y', <function X.y at 0x1006ee3b0>)
like image 742
Doug Avatar asked Jun 10 '13 08:06

Doug


People also ask

What is inspect Python?

The inspect module provides several useful functions to help get information about live objects such as modules, classes, methods, functions, tracebacks, frame objects, and code objects.


1 Answers

Not specifically a difference with inspect but Python 3 in general see here

The concept of “unbound methods” has been removed from the language. When referencing a method as a class attribute, you now get a plain function object.

My suggestion for cross-platform would be:

getmembers(X, predicate=lambda x: isfunction(x) or ismethod(x))
like image 89
jamylak Avatar answered Sep 18 '22 14:09

jamylak