包子模块查看导入程序所有类的最轻松的技术

特雷弗

背景问题

python程序会导入一些模块,每个模块都会创建各种类。它还导入了带有子模块的软件包,该子模块需要能够查看python程序顶层的所有可用类。包子模块如何查看其导入器可用的所有类?

这是我当前的解决方案,它可以工作,但是它需要顶层程序从子模块创建一个实例,并通过globals()实例方法(请参见下文)将其传递给字典。至少在导入包的子模块之后,只需执行一次。

这将是一个更好的方法,它要求顶级方案的通过globals()我希望这种情况自动发生,如果可能的话,对顶级程序是透明的。

带注释的输出

$ python top_t.py 
Hi, I'm an instance of ModM!
# Expected, but not desired.
ModM in SubModS:0's globals = No
Adding globals from higher level to level of SubModS.
# Yeah!
ModM in SubModS:0's globals = Yes
# Persistent
ModM in SubModS:1's globals = Yes
# Sufficient to create a new instance from submodule.
Hi, I'm an instance of ModM!

代码

top_t.py

from mod_m import ModM
from package_p import SubModS

m0 = ModM()
s0 = SubModS(0)

s0.see_class('ModM')
s0.broaden_view(globals())
s0.see_class('ModM')
s1 = SubModS(1)
s1.see_class('ModM')
m1 = s0.create_inst('ModM')

mod_m.py

class ModM(object):
    def __init__(self):
        print "Hi, I'm an instance of ModM!"

package_p / __ init__.py

__all__ = ['SubModS']
from .submod_s import SubModS

package_p / submod_s.py

class SubModS(object):
    def __init__(self, i):
        self.i = i
    def see_class(self, cls):
        print "{} in {}:{}'s globals = {}".format(cls, self.__class__.__name__, self.i, 'Yes' if cls in globals() else 'No')
    def broaden_view(self, higher_globals):
        print 'Adding globals from higher level to level of {}.'.format(self.__class__.__name__)
        local_globals = globals()
        for nm, ob in higher_globals.iteritems():
            if nm not in local_globals:
                local_globals[nm] = ob
    def create_inst(self, cls):
        return globals()[cls]()
特雷弗

在考虑了BrenBarn的评论并探索(搜索)Python插件框架之后,我决定根据以下链接创建一个非常简单的适合我的需求的框架:

上面示例的修改后的版本如下所示(请参见下文)。

关键是使用元类,以基于中央便利基类为基础,收集所有类的列表。

节目输出

$ python top_t.py
Hi, I'm instance #0 of SubModS!
Can ModM be seen by SubModS:0?  Yes!
Can UnBasedClass be seen by SubModS:0?  No!
Hi, I'm instance #0 of ModM!
Hi, I'm instance #1 of ModM!
Can SubModS be seen by ModM:1?  Yes!
Hi, I'm instance #1 of SubModS!

代码

top_t.py

from mod_m import ModM
from package_p import SubModS

s0 = SubModS()
s0.see_class('ModM')
s0.see_class('UnBasedClass')
s0.create_inst('ModM')

m0 = ModM()
m0.see_class('SubModS')
m0.create_inst('SubModS')

mod_m.py

from package_p import PluginBase
class ModM(PluginBase):
    def __init__(self):
        super(ModM, self).__init__()

package_p / __ init__.py

__all__ = ['SubModS', 'PluginBase']
from .meta_base import PluginBase
from .submod_s import SubModS

package_p / submod_s.py

from .meta_base import PluginBase
class SubModS(PluginBase):
    def __init__(self):
        super(SubModS, self).__init__()

package_p / meta_base.py

class PluginMount(type):
    def __init__(cls, name, bases, attrs):
        if not hasattr(cls, 'plugins'):
            cls.plugins = []
        else:
            cls.plugins.append(cls)

class PluginBase(object):
    __metaclass__ = PluginMount
    i = 0
    def __init__(self):
        self.i = self.__class__.i
        print "Hi, I'm instance #{} of {}!".format(self.i, self.__class__.__name__)
        self.__class__.i += 1
    def see_class(self, name):
        print "Can {} be seen by {}:{}?  {}!".format(name, self.__class__.__name__, self.i, 'Yes' if name in (cls.__name__ for cls in self.__class__.plugins) else 'No')
    def create_inst(self, name):
        for cls in self.__class__.plugins:
            if name == cls.__name__:
                return cls()
        return None

希望这对其他人有帮助!

当然也欢迎其他方法和评论。

谢谢!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章