【问题标题】:Finding a specific class from any given module从任何给定模块中查找特定类
【发布时间】:2013-05-28 12:46:41
【问题描述】:

一般情况:

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

我什至没有得到具体的代码,或者我会发布它。不过我想我有一些选择:

  1. 只需通过try/except运行模块中的所有内容
  2. if/else求我需要的方法
  3. 使用检查来查找模块中类的完全匹配
  4. 使用元类添加属性this_is_class_sought=True

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:

__subclasses__() 大大简化了我的目的。

【问题讨论】:

  • 执行此操作的正常方法是将所有这些类显式导入主模块。与编写一些在运行时为您执行此操作的魔术代码相比,让所有这些导入语句保持最新所需的工作量更少。
  • 有一点我可能没有强调:我不知道我会得到什么模块或视图。我知道明确导入模块会更容易,但我不会事先知道我将使用哪些模块,它们将包含哪些视图,或者它们将包含多少个视图。

标签: python flask flask-extensions


【解决方案1】:

听起来你正在尝试做一些 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

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

【讨论】:

  • @blueblank:不知道,亲爱的 :)
猜你喜欢
  • 1970-01-01
  • 2020-10-31
  • 2010-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多