使用super的问题(python 2.5.2)

时间:2009-03-04 21:18:14

标签: python introspection python-datamodel

我正在为我的程序编写一个插件系统,我无法解决一件事:

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

我环顾四周,我根本不知道发生了什么。

2 个答案:

答案 0 :(得分:20)

'super'是内置的。除非你不顾一切地删除内置函数,否则你不应该看到“全局名称'super'未定义”。

我正在看你的user web link那里有一个IntrospectionHelper的转储。没有缩进就很难阅读,但看起来你可能正是这样做的:

built_in_list = ['__builtins__', '__doc__', '__file__', '__name__']

for i in built_in_list:
    if i in module.__dict__:
        del module.__dict__[i]

这是原始模块,你在那里改变,而不是你将要返回的信息副本!从实时模块中删除这些成员,你可以期待比“超级”更多的东西。

很难跟踪该模块正在做什么,但我的反应是它有太大的魔力。平均Python程序永远不需要乱搞导入系统,sys.path和monkey-patching __magic__模块成员。一点点魔法可以是一个巧妙的技巧,但这是非常脆弱的。只是在浏览它之后,代码可能被以下内容破坏:

  • 名称与顶级模块发生冲突
  • 任何使用新式课程
  • 仅作为编译的字节码提供的模块
  • zipimporter

从getClassDefinitions,extractModuleNames和isFromBase这些令人难以置信的圆形函数中,我觉得你仍然需要了解Python工作原理的基础知识。 (线索:getattr,模块.__ name__和issubclass。)

在这种情况下现在是潜入进口魔术的时间!这是很难。相反,做正常的Python方式。在包的mypackage / __ init __的底部说一下可能会多一点打字.py:

from mypackage import fooplugin, barplugin, bazplugin
plugins= [fooplugin.FooPlugin, barplugin.BarPlugin, bazplugin.BazPlugin]

但它会起作用并且在任何地方都能被理解,而不依赖于一堆复杂,脆弱的魔法。

顺便说一下,除非你计划进行一些深入的多重继承工作(现在可能不是时候了),你甚至可能不需要使用super()。调用已知超类的通常的“IPlugin .__ init __(self,...)”方法是直截了当的事情;在你开始使用它之前,super()并不总是“更新,更好的做事方式”和there are things you should understand about it

答案 1 :(得分:0)

除非您运行的是早于2.2的Python版本(非常不可能),super()绝对是built-in function(在每个范围内都可用,并且不会导入任何内容)。

可能值得检查你的Python版本(只需在命令行输入python启动交互式提示)。