动态加载继承模块

问题描述:

我知道这个主题有几个帖子,但是由于什么原因,我无法理解它,或至少实现它。以下是我正在尝试做的一些示例代码。动态加载继承模块

基类:

class Animal(object): 

    def __init__(self, age): 
     self._age = age 

    def getAge(self): 
     return self._age 

    def speak(self): 
     raise NotImplementedError() 

    def speak_twice(self): 
     self.speak() 
     self.speak() 

子类

from Animal import Animal 
class Dog(Animal): 
    def speak(self): 
     print "woff!" 

测试代码

mod = __import__("Dog") 
spot = mod(5) 

运行试验后的代码我得到这个错误:

Traceback (most recent call last): 
    File "C:~test.py", line 2, in <module> 
    spot = mod(5) 
TypeError: 'module' object is not callable 

所以基本上我的问题是如何动态加载模块和初始化正确呢?

编辑:

我不知道子类,直到运行时

您必须导入模块本身,然后得到它的类成员。你不能只导入这个类。假设你的子类是在一个文件从PYTHONPATH为“动物”访问:

mod = __import__('animal') 
spot = mod.Dog(5) 

当您导入模块,解释首先查看是否有该名称的模块中sys.modules存在,那么如果它没有在那里找到它,它会搜索pythonpath,查找与给定名称匹配的包或模块。如果找到一个,它会解析其中的代码,从中建立一个模块对象,将它放在sys.modules上,并将模块对象返回给调用范围,以便绑定到在给定名称空间中导入的名称。然后模块范围内的模块(类,变量,函数)中的所有项目(不嵌套在代码中的其他内容中)作为该模块实例的成员可用。

编辑:

在回答您的意见,真正的问题是,你试图动态查找该模块的属性,不是你试图动态导入任何东西。最直接的方式做到这一点是:

import sub_animal 
getattr(sub_animal, 'Dog') 

但是,如果你试图动态地确定类基于一些条件来初始化,你可能想在​​读了,并且可能decorators甚至metaclasses,以便您可以动态地将子类自动添加到工厂。

class AnimalFactory(type): 

    animal_classes = {} 

    def __new__(cls, name, bases, attrs): 

     new_class = super(AnimalFactory, cls).__new__(cls, name, bases, attrs) 
     AnimalFactory.animal_classes[name] = new_class 
     return new_class 

    @classmethod 
    def build(cls, name, *args, **kwargs): 

     try: 
      klass = cls.animal_classes[name] 
     except KeyError: 
      raise ValueError('No known animal %s' % name) 
     return klass(*args, **kwargs) 

class Animal(object): 

    __metaclass__ = AnimalFactory 

    def __init__(self, age): 

     self.age = age 

    def speak(self): 

     raise NotImplementedError() 

# As long as the file it is implemented in is imported at some point, 
# the following can be anywhere 

class Dog(Animal): 

    def speak(self): 

     return 'woof' 

# And then to use, again, anywhere 

new_animal = AnimalFactory.build('Dog', 5) 
+0

如果我直到运行时才知道类成员,那该怎么办? – Richard

+2

试试'spot = getattr(mod,'Dog')(5)' – zigg

+0

@zigg谢谢,那有效! – Richard