从任何给定模块中查找特定类

时间:2013-05-28 12:46:41

标签: python flask flask-extensions

一般情况:

  • 我不知道我将事先检查哪些模块,我不知道它们将会是什么:类,方法等。
  • 我确实知道我正在寻找什么课程,以及我需要做什么。例如我需要运行一个特定的方法cls.register
  • 我需要找到最有效的方法。

我甚至没有得到具体的代码,或者我发布了它。不过我认为我有一些选择:

  1. 只需通过try / except
  2. 运行模块中的所有内容即可
  3. if / else寻找我需要的方法
  4. 使用inspect查找模块中类的完全匹配
  5. 使用元类添加属性this_is_class_sought=True
  6. 1-3看起来太粗糙,4似乎太费劲了。

    我的情况:

    我尝试将Flask-Classy与an application creator/factory集成 我有一堆视图文件,我不知道这些文件中会有什么。我需要找到子类FlaskView的所有类,但不是FlaskView本身,然后运行类注册函数。

    因此,例如从dir(a_module)随机遇到的模块:

    ['FlaskView', 'AView', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'forms', 'models', 'redirect', 'render_template', 'request', 'url_for']

    我需要确定AView是否存在,然后运行注册方法。 3,上面似乎很可能,但我还没有确切地确定如何区分AView

    这样做的最佳方式是什么?

    编辑:

    我必须强调,重点是我不知道我将要查看哪些模块,或者它们将包含哪些模块。我需要有效地提取我需要的信息并根据这些信息采取行动。

    EDIT2:

    __ subslasses __()简化了我的目的。

1 个答案:

答案 0 :(得分:0)

听起来你正在尝试做一些hacky,但是......无论如何我都会帮帮忙的。如果选项4是一个选项,那么我建议使用自注册的元类/基类。

看一下这个答案:Generic Python metaclass to keep track of subclasses

复制完整性

def sublass_registry():
    ''' Create a metaclass to register subclasses '''

    class SublassRegistryMeta(type):
        def __init__(cls, name, bases, classdict):
            if classdict.get('__metaclass__') is SublassRegistryMeta:
                SublassRegistryMeta.lineage = [cls] # put root class at head of a list
            else:
                # sublclasses won't have __metaclass__ explicitly set to this class
                # we know they're subclassees because this ctor is being called for them
                SublassRegistryMeta.lineage.append(cls) # add subclass to list
            type.__init__(cls, name, bases, classdict)

    return SublassRegistryMeta

def subclasses(cls):
    ''' Return a list containing base and subclasses '''

    try:
        if cls.__metaclass__.lineage[0] is cls: # only valid for a root class
            return cls.__metaclass__.lineage
    except AttributeError:
        pass
    return None

class Car(object): # root class
    __metaclass__ = sublass_registry()

class Audi(Car): # inherits __metaclass__
    pass

class Ford(Car): # inherits __metaclass__
    pass

class Audi2(Audi): # sub-subclass also inherits __metaclass__
    pass

print subclasses(Car)
# [<class '__main__.Car'>, <class '__main__.Audi'>, <class '__main__.Ford'>, <class '__main__.Audi2'>]
print subclasses(Audi)
# None

或者,只需使用一些issubclassisinstance循环播放它就可以了。一般来说,你不需要任何尝试/除了这里,但为了安全起见,你可以添加一些。