重写没有inspect模块的Python函数

2 投票
3 回答
717 浏览
提问于 2025-04-16 14:43

我该如何编写这个自省函数,而不使用inspect模块呢?

import inspect

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

上面的内容来自于 这个StackOverflow的问题/答案

编辑/澄清:有没有可能在不导入任何模块的情况下做到这一点?

请注意,这并不是一个真实的使用案例,而只是出于我个人的好奇心。

3 个回答

2

inspect.ismethod的作用就是简单地判断一个东西是不是方法。

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

types.MethodType定义为

class _C:
   def _m(self): pass
MethodType = type(_C()._m)
2

不使用检查工具,我会这样做:

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

编辑:

你的限制条件有点奇怪,不过我们来看看:

我们可以把 if isinstance(attr, types.MethodType) 替换成 if callable(attr),这样就只会得到类中可以调用的属性,这也包括静态方法和类方法……

我们也可以按照其他回答的建议,使用 if hasattr(attr, 'im_func'),这样就会排除静态方法。

如果我们想要排除类方法,只获取实例方法,我现在知道的唯一解决办法(不需要导入其他模块)就是修改装饰器,检查第一个参数是类还是实例,这样可以帮助你判断被装饰的方法是类方法还是实例方法。

希望这能帮到你 :)

2

大概是这样的:

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

在Python的文档中,关于数据模型的部分,往下滚动一点就能找到“用户定义的方法”。

一些特殊的只读属性:im_self是类实例对象,im_func是函数对象;im_class是im_self的类,对于绑定方法来说,或者是请求这个方法的类,对于未绑定的方法来说;__doc__是这个方法的文档(和im_func.__doc__是一样的);__name__是方法的名字(和im_func.__name__是一样的);__module__是定义这个方法的模块的名字,如果没有则为None。

从2.6版本开始,im_func和im_self也可以用__func____self__来表示。我个人比较倾向于使用这些,而不是使用inspect模块。

撰写回答