0

我知道有几篇关于这个主题的帖子,但是出于某种原因,我无法理解它,或者至少无法实现它。下面是我正在尝试做的一些示例代码。

基类:

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

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

编辑:

直到运行时我才知道子类

4

1 回答 1

3

您必须导入模块本身,然后获取其类成员。你不能只导入类。假设您的子类位于可从 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)
于 2013-01-23T15:05:37.683 回答