私はテキストベースのアドベンチャーゲームに取り組んでおり、すべてのアクションクラスを持つモジュールを持っていMove(Action)
ますLook(Action)
. クラスのサブクラスであるモジュール内のすべてのクラスをAction
次のようなリストにインスタンス化する方法が必要です。
actions = [Move(), Look()]
名前を入力してクラスを個別にインスタンス化することなく、これを行う方法はありますか?
私はテキストベースのアドベンチャーゲームに取り組んでおり、すべてのアクションクラスを持つモジュールを持っていMove(Action)
ますLook(Action)
. クラスのサブクラスであるモジュール内のすべてのクラスをAction
次のようなリストにインスタンス化する方法が必要です。
actions = [Move(), Look()]
名前を入力してクラスを個別にインスタンス化することなく、これを行う方法はありますか?
これは機能します:
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
。
obj is not Action
-Action
はそれ自体のサブクラスであるため、フィルターで除外する必要があります。
isinstance(obj, type)
- オブジェクトはクラスでなければなりません。そうしないと、3.のテストができなくなります。
issubclass(obj, Action)
- 最後に、サブクラスのテストを実行できます。
これで、フィルタリングされたすべてのクラスのインスタンスを作成し、それらをリストに追加できます。
actions.append(obj())
すべてのクラスが 1 つのモジュールで定義されていることが確実な場合、または複数のモジュールに分散されたすべてのサブクラスが必要な場合でも、これははるかに短くなります。
>>> actions = [obj() for obj in Action.__subclasses__()]
>>> actions
[<__main__.Move at 0x10fc14fd0>, <__main__.Look at 0x10fc14668>]
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]