当前位置:  开发笔记 > 编程语言 > 正文

使用Python全局变量的动态类的最佳方法()

如何解决《使用Python全局变量的动态类的最佳方法()》经验,为你挑选了1个好方法。

我正在开发一个Web应用程序,它将根据用户输入返回一组可变模块.每个模块是一个Python类与接受单个参数,并且具有包含在输出一个"html的"属性的构造函数.

从全局命名空间动态提取类的工作原理如下:

result = globals()[classname](param).html

而且它肯定比以下更简洁:

if classname == 'Foo':
    result = Foo(param).html
elif classname == 'Bar':
    ...

什么被认为是风格上写这个的最佳方式?是否存在不使用全局命名空间的风险或原因?



1> Brian..:

这种方法的一个缺陷是它可能使用户能够比你想要的更多.他们可以通过提供名称来调用该命名空间中的任何单参数函数.您可以通过一些检查来帮助防范这种情况(例如isinstance(SomeBaseClass,theClass),但它可能更好地避免这种方法.另一个缺点是它限制了您的类位置.如果您最终得到了几十个这样的类并决定要将它们分组到模块中,您的查找代码将停止工作.

您有几种备选方案:

    创建显式映射:

     class_lookup = {'Class1' : Class1, ... }
     ...
     result = class_lookup[className](param).html
    

    虽然这样做的缺点是你必须重新列出所有的类.

    将类嵌套在封闭范围内.例如.在他们自己的模块中或在外部类中定义它们:

    class Namespace(object):
        class Class1(object):
            ...
        class Class2(object):
            ...
    ...
    result = getattr(Namespace, className)(param).html
    

    你在这里无意中暴露了一些额外的类变量(__bases __,__ getattribute__等) - 可能无法利用,但并不完美.

    从子类树构造一个查找字典.使所有类继承自单个基类.创建所有类后,检查所有基类并从中填充dict.这样做的好处是你可以在任何地方定义你的类(例如,在单独的模块中),只要你在创建注册表之后创建注册表,你就会找到它们.

    def register_subclasses(base):
        d={}
        for cls in base.__subclasses__():
            d[cls.__name__] = cls
            d.update(register_subclasses(cls))
        return d
    
    class_lookup = register_subclasses(MyBaseClass)
    

    上面的一个更高级的变体是使用自注册类 - 创建一个元类,而不是自动在dict中注册任何创建的类.对于这种情况,这可能有点过头了 - 但它在一些"用户插件"场景中很有用.

推荐阅读
雯颜哥_135
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有