在Python中使用Reflection或Introspection寻求一种不同的方式

时间:2013-11-08 21:15:17

标签: python reflection introspection

我正在重构一些代码,我想我可以使用一点反射!所以,我现在有这个:

def f(self, clazz):
    [...]
    boolean = False
    if hasattr(clazz_instace, 'some_attribute'):
        setattr(clazz_instace, 'some_attribute', True)
        boolean = True

    if boolean:
        result = getattr(clazz_instace, 'another_method')(None, request=request)
        return result['objects']

    sorted_objects = getattr(clazz_instace, 'One_more_method')(request)
    result = getattr(clazz_instace, 'another_method')(sorted_objects, request=request)

    return [...]

我的问题是关于我用来指示我正在搜索关于clazz_instance的方法的字符串。我想知道是否还有另一种最好的方式来做我所做的事情(以一种特殊的动态方式)?我的意思是,像我一样直接把方法的名字像字符串一样,如果我能用不同的方式验证这些方法,那将是非常好的。

你能提出一些好主意吗?你会怎么做?

提前致谢!!!

2 个答案:

答案 0 :(得分:1)

实例的方法只不过是存储在实例function中的__dict__对象。这样说,你找对它们是正确的,除了可能,类确实具有与你的参数字符串对应的属性,但不是函数,而只是另一种类型。

如果您依赖于此,我建议您将实例的函数代码重构为辅助方法:

import types
def instance_has_method(instance, name):
    try:
        attr = getattr(instance, name)
        return isinstance(attr, types.FunctionType)
    except AttributeError:
        return False

一旦你有了这个功能,你的代码将更加简洁,因为现在你确定该属性确实是一个函数并且可以被调用。

上面的代码检查属性是否为函数。如果你想要更广泛的东西,你可以检查它是callable是这样的:return hasattr(attr, '__call__')

在python中,这基本上就是你如何检查类中的属性。我不认为你的方法没有错,也没有另一种更聪明的方法来做反思。

希望这有帮助!

答案 1 :(得分:0)

理解你想要达到的目标并不容易。

getattr(clazz_instace, 'One_more_method')(request)只是说clazz_instace.One_more_method(request)的一种奇特方式。

如果您事先不知道方法名称,即方法名称是可变的,则使用getattr是合理的。

此外,setattr(clazz_instace, 'some_method_inside_this_class', True)将涉嫌some_method_inside_this_class转换为该类中的标量属性,其值为True。可能这不是你计划的。

我尽最大努力了解您的代码:

def f(clazz):
  # if clazz is capable of better_processing, use it:
  if hasattr(clazz, 'better_processing'):
    return clazz.better_processing(...)
  else:
    return clazz.basic_processing(...)

BTW getattr给你的是一个可调用的方法,你可以直接使用它,如下所示:

method = getattr(clazz, 'better_method', clazz.default_method)
# if 'better_method' was available, it was returned by getattr;
# if not, the default method was returned.
return method(clazz_instance, some_data...)