Problema usando super (python 2.5.2)
-
03-07-2019 - |
Pergunta
Eu estou escrevendo um sistema de plugins para o meu programa e eu não posso passar por uma coisa:
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
O teste do plugin parecido com este:
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)
Agora, o IPlugin parece com isso:
class IPlugin(object):
'''
classdocs
'''
name=''
def __init__(self, loader):
self.loader=loader
def activate(self):
pass
Todas as classes IPlugin funciona flawlessy por eles mesmos, mas quando chamado por ThingLoader o programa recebe uma exceção:
File "./plugins\TestPlugin.py", line 13, in __init__
super(TestPlugin, self).__init__(loader) NameError:
global name 'super' is not defined
Eu olhei ao redor e eu simplesmente não sei o que está acontecendo.
Solução
‘super’ é um builtin. A menos que você saiu do seu caminho para builtins de exclusão, você não deve nunca ver “nome global 'super' não está definido”.
Eu estou olhando para o seu user link web onde há um despejo de IntrospectionHelper. É muito difícil de ler sem o recuo, mas parece que você pode estar fazendo exatamente isso:
built_in_list = ['__builtins__', '__doc__', '__file__', '__name__']
for i in built_in_list:
if i in module.__dict__:
del module.__dict__[i]
Isso é o módulo original dict você está mudando lá, não uma cópia de informação que você está prestes a troca! Excluir esses membros de um módulo ao vivo e você pode esperar muito mais do que ‘super’ para quebrar.
É muito difícil manter o controle do que esse módulo está fazendo, mas minha reação é que há demasiada magia. O programa de média Python nunca precisará ser brincando com o sistema de importação, sys.path e-remendar macaco __magic__ membros do módulo. Um pouco de magia pode ser um truque, mas isso é extremamente frágil. Apenas fora do topo da minha cabeça de navegar ele, o código poderia ser quebrado por coisas como:
- confrontos com nome módulos de nível superior
- qualquer uso de classes de estilo novo
- módulos fornecidas apenas como bytecode compilado
- zipimporter
Do incrivelmente rotunda funções como getClassDefinitions, extractModuleNames e isFromBase, parece-me que você ainda tem um pouco para aprender sobre os conceitos básicos de como Python funciona. (Pistas:. GetAttr, módulo .__ name__ e issubclass, respectivamente)
Neste caso agora é não o tempo para estar mergulhando em magia de importação! É duro . Em vez disso, fazer as coisas O normal Python caminho. Pode ser um pouco mais digitando a dizer na parte inferior de um pacote é mypackage / __ o init __ py:.
from mypackage import fooplugin, barplugin, bazplugin
plugins= [fooplugin.FooPlugin, barplugin.BarPlugin, bazplugin.BazPlugin]
mas ele vai trabalhar e ser compreendido em todos os lugares, sem depender de um ninho de complexo mágica, frágil.
A propósito, a menos que você está pensando em alguns em profundidade o trabalho de herança múltipla (e novamente, agora pode não ser o momento para isso), você provavelmente não precisa nem usar super (). O usual “IPlugin .__ o init __ (self, ...)” método de chamar uma superclasse conhecida é a coisa simples de fazer; super () nem sempre é “a melhor maneira nova, de fazer as coisas” e há coisas que você deve entender sobre isso antes de ir carregar em usá-lo.
Outras dicas
A menos que você estiver executando uma versão do Python mais cedo do que 2.2 (muito improvável), super()
é definitivamente um built-in função (disponível em todos os âmbitos, e sem importar nada).
Pode valer a pena verificar a sua versão do Python (simplesmente iniciar o prompt interativo, python digitando na linha de comando).