10

私はテキストベースのアドベンチャーゲームに取り組んでおり、すべてのアクションクラスを持つモジュールを持っていMove(Action)ますLook(Action). クラスのサブクラスであるモジュール内のすべてのクラスをAction次のようなリストにインスタンス化する方法が必要です。

actions = [Move(), Look()]

名前を入力してクラスを個別にインスタンス化することなく、これを行う方法はありますか?

4

2 に答える 2

8

解決

これは機能します:

class Action:
    pass

class Move(Action):
    pass

class Look(Action):
    pass


actions = []
global_objs = list(globals().items())

for name, obj in global_objs:
    if obj is not Action and isinstance(obj, type) and issubclass(obj, Action):
        actions.append(obj())
print(actions)

プリント:

[<__main__.Move object at 0x101916ba8>, <__main__.Look object at 0x101916be0>]

手順

まず、現在のモジュール内のオブジェクトのすべての名前を取得します。

global_objs = list(globals().items())

items()Python 3では、基になる辞書の変更を反映する dictview オブジェクトを返すため、リストに変換する必要があり ます。同じモジュールで作業しているため、新しいオブジェクトを定義すると、この辞書が変更されます。リストに変換すると、この問題が解決します。

次に、すべてのオブジェクトを調べます。のサブクラスになるには、次の 3 つの条件を満たす必要がありますAction

  1. obj is not Action-Actionはそれ自体のサブクラスであるため、フィルターで除外する必要があります。

  2. isinstance(obj, type)- オブジェクトはクラスでなければなりません。そうしないと、3.のテストができなくなります。

  3. issubclass(obj, Action)- 最後に、サブクラスのテストを実行できます。

これで、フィルタリングされたすべてのクラスのインスタンスを作成し、それらをリストに追加できます。

actions.append(obj())

短いバージョン

すべてのクラスが 1 つのモジュールで定義されていることが確実な場合、または複数のモジュールに分散されたすべてのサブクラスが必要な場合でも、これははるかに短くなります。

>>> actions = [obj() for obj in Action.__subclasses__()]
>>> actions
[<__main__.Move at 0x10fc14fd0>, <__main__.Look at 0x10fc14668>]
于 2016-01-01T09:15:33.947 に答える
1
from other_module import Action

def is_action_class(var):
    return var != Action and type(var) == type and issubclass(var, Action)

classes = []    

for attr in dir(my_module):
    var = getattr(my_module, attr)
    if is_action_class(var):
        classes.append(var)
instances = [c() for c in classes]
于 2016-01-01T09:15:08.560 に答える