2

How would I write this introspective function without using the inspect module.

import inspect

def trace(cls):
    for name, m in inspect.getmembers(cls, inspect.ismethod):
        setattr(cls,name,log(m))
    return cls

The above is from this SO question/answer

Edit/Clarification: Is it possible to do this without any imports also?

Note this is not a real use case rather a pure and simple case of curiosity on my part.

Community
  • 1
  • 1
Preet Sangha
  • 64,563
  • 18
  • 145
  • 216
  • What is meant by "didn't have access to the import module"? You can `import` inside the function `trace`. – kennytm Mar 30 '11 at 09:16

3 Answers3

2

something like this:

>>> class Tester(object):
...   def mymethod(self):
...     return True
... 
>>> hasattr(Tester, 'mymethod')
True
>>> hasattr(Tester.mymethod, 'im_func')
True

from the python docs on the data model scroll down a bit to get to "user defined methods".

Special read-only attributes: im_self is the class instance object, im_func is the function object; im_class is the class of im_self for bound methods or the class that asked for the method for unbound methods; __doc__ is the method’s documentation (same as im_func.__doc__); __name__ is the method name (same as im_func.__name__); __module__ is the name of the module the method was defined in, or None if unavailable.

im_func and im_self as of 2.6 are also availabale as __func__ and __self__ respectively. I sort of tend to gravitate here than use the inspect module myself.

Rob Bednark
  • 25,981
  • 23
  • 80
  • 125
Mike Ramirez
  • 10,750
  • 3
  • 26
  • 20
2

What inspect.ismethod does is simply:

import types
def ismethod(obj):
   return isinstance(obj, types.MethodType)

and types.MethodType is defined as:

class _C:
   def _m(self): pass
MethodType = type(_C()._m)
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
2

Without using inspect i will do it like this:

import types

def trace(cls):
    for attr_name in cls.__dict__:
        attr = getattr(cls, attr_name)
        if isinstance(attr, types.MethodType):
            setattr(cls, attr_name, log(attr))
    return cls

EDIT:

Your constrain are a bit weird but let see :

We can replace if isinstance(attr, types.MethodType) by if callable(attr) this will give us only callable attribute of the class which include also static methods and class methods ...

We can also do as the other answer suggest use if hasattr(attr, 'im_func') this will exclude the static methods.

If we want to exclude class method too (only get instance method), i think the only solution i'm aware off now (without importing an other module) is by changing the decorator to check if the first argument is a class or an instance, this can give you a hint if the method that will be decorated is a class or a instance method.

Hope it help :)

mouad
  • 67,571
  • 18
  • 114
  • 106