【问题标题】:Problem using super(python 2.5.2)使用超级问题(python 2.5.2)
【发布时间】:2010-10-11 09:06:35
【问题描述】:

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

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

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

【问题讨论】:

  • 在阅读了接受的答案后,我很想对这个不完整和误导性的问题投反对票。

标签: python introspection python-datamodel


【解决方案1】:

‘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 和猴子补丁 __magic__ 模块成员。一点点魔法可以是一个巧妙的技巧,但这非常脆弱。刚刚浏览它,代码可能会被以下内容破坏:

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

从 getClassDefinitions、extractModuleNames 和 isFromBase 等令人难以置信的迂回函数来看,在我看来,您对 Python 工作原理的基础知识还有很多东西需要了解。 (线索:分别是 getattr、module.__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 用于实际跟踪用户页面链接以找到代码副本,然后对其进行调试。这一定是有史以来研究最彻底的答案之一。
  • 他应该从中获得奖励!
  • 写这个答案一定很愉快。 +1
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2010-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-18
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多