0

背景の問題

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]()
4

1 に答える 1

0

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

これが他の誰かに役立つことを願っています!

他のアプローチやコメントは大歓迎です。

ありがとう!

于 2013-11-01T23:07:27.670 に答える