super(python 2.5.2)の使用に関する問題
-
03-07-2019 - |
質問
プログラム用のプラグインシステムを作成していますが、1つのことを忘れることができません:
class ThingLoader(object):
'''
Loader class
'''
def loadPlugins(self):
'''
Get all the plugins from plugins folder
'''
from diones.thingpad.plugin.IntrospectionHelper import loadClasses
classList=loadClasses('./plugins', IPlugin)#Gets a list of
#plugin classes
self.plugins={}#Dictionary that should be filled with
#touples of objects and theirs states, activated, deactivated.
classList[0](self)#Runs nicelly
foo = classList[1]
print foo#prints <class 'TestPlugin.TestPlugin'>
foo(self)#Raise an exception
テストプラグインは次のようになります。
import diones.thingpad.plugin.IPlugin as plugin
class TestPlugin(plugin.IPlugin):
'''
classdocs
'''
def __init__(self, loader):
self.name='Test Plugin'
super(TestPlugin, self).__init__(loader)
IPluginは次のようになります。
class IPlugin(object):
'''
classdocs
'''
name=''
def __init__(self, loader):
self.loader=loader
def activate(self):
pass
すべてのIPluginクラスは問題なく動作しますが、ThingLoaderによって呼び出されると、プログラムは例外を取得します。
File "./plugins\TestPlugin.py", line 13, in __init__
super(TestPlugin, self).__init__(loader) NameError:
global name 'super' is not defined
私はあちこちを見回しましたが、何が起こっているのかわかりません。
解決
&#8216;スーパー&#8217;組み込みです。ビルトインを削除するために邪魔にならない限り、&#8220;グローバル名 'super' is not defined&#8221;が表示されることはありません。
IntrospectionHelperのダンプがあるユーザーのWebリンクを見ています。インデントなしで読むことは非常に難しいですが、あなたはまさにそれをしているように見えます:
built_in_list = ['__builtins__', '__doc__', '__file__', '__name__']
for i in built_in_list:
if i in module.__dict__:
del module.__dict__[i]
これは、変更しようとしている情報コピーではなく、そこで変更する元のモジュール辞書です!ライブモジュールからこれらのメンバーを削除すると、&#8216; super&#8217;破る。
そのモジュールが何をしているかを追跡するのは非常に難しいですが、私の反応は、あまりにも多くの魔法があります。平均的なPythonプログラムは、インポートシステム、sys.path、およびモンキーパッチの__magic__モジュールメンバーをいじる必要はありません。ちょっとした魔法はきちんとしたトリックになりますが、これは非常に脆弱です。ブラウジングから私の頭のすぐ外で、コードは次のようなものによって壊れる可能性があります:
- 名前がトップレベルのモジュールと衝突する
- 新しいスタイルのクラスの使用
- コンパイル済みバイトコードとしてのみ提供されるモジュール
- zipimporter
getClassDefinitions、extractModuleNames、isFromBaseなどの信じられないほどのラウンドアバウト関数から、Pythonがどのように動作するかの基本についてまだ学ぶべきことがたくさんあるように思えます。 (手がかり:それぞれgetattr、module .__ name __、issubclass。)
この場合、インポートマジックに飛び込むのは今ではありません !それは hard です。代わりに、The Normal Python Wayを実行してください。パッケージのmypackage / __ init__.pyの最後に言うのはもう少し入力するかもしれません:
from mypackage import fooplugin, barplugin, bazplugin
plugins= [fooplugin.FooPlugin, barplugin.BarPlugin, bazplugin.BazPlugin]
しかし、複雑で壊れやすい魔法の巣に頼ることなく、それはどこでも動作し、理解されます。
ちなみに、いくつかの詳細な多重継承作業を計画しているのでなければ(そして、今はその時ではないかもしれません)、おそらくsuper()を使用する必要さえありません。通常の&#8220; IPlugin .__ init __(self、...)&#8221;既知のスーパークラスを呼び出す方法は、簡単なことです。 super()は常に&#8220;より新しく、より良い方法であるとは限りません&#8221;および使用を開始する前に理解しておくべきことがあります。
他のヒント
2.2より前のバージョンのPythonを実行していない限り(かなりありそうにない)、 super()
は間違いなく組み込み関数(すべてのスコープで、何もインポートせずに使用可能)。
Pythonのバージョンを確認する価値がある場合があります(コマンドラインでpythonと入力して対話型プロンプトを起動するだけです)。