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から「animal」としてアクセス可能なファイルにあると仮定します。

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 に答える