2017-12-30 26 views
1

クラスのリストからクラスのインスタンスを作成するにはどうすればよいですか?私は他のSOの答えを見てきましたが、それらを理解しました。クラスのリストからインスタンスを作成する

私はクラスのリストを持っている:クラスを格納する変数の名前がクラスの名前です

list_of_classes = [Class1, Class2] 

は、今私は、これらのクラスのインスタンスを作成します。私は試してみました:

for cls in list_of_classes: 
    str(cls) = cls() 

しかし、エラー: "SyntaxError:関数呼び出しに割り当てることができません"。それはもちろん明らかですが、私は何をすべきか分かりません。

本当に名前でクラスにアクセスしたいと思っています。すべてのインスタンスを辞書に保存し、クラスの1つがClassAであるとしたら、後でdict ['ClassA']でインスタンスにアクセスできるようにしたいとします。それは可能ですか?より良い方法がありますか?

+0

がに割り当てることができません。

def my_named_tuple(attribute_names): class Tup: def __init__(self, *args): if len(args) != len(attribute_names): raise ValueError("Wrong number of arguments") for name, value in zip(attribute_names, args): setattr(self, name, value) # this programmatically sets attributes by name! def __iter__(self): for name in attribute_names: yield getattr(self, name) # you can look up attributes by name too def __getitem__(self, index): name = attribute_names[index] if isinstance(index, slice): return tuple(getattr(self, n) for n in name) return getattr(self, name) return Tup 

それは、このように動作します関数呼び出しは 'str(cls)= cls()'の左部分を意味します。おそらく 'str [cls] = cls()'を意味します。しかし、これはforループの前に 'str = dict()'を置いた場合にのみ有効です。それを試すことができますか? – hansaplast

答えて

0

私が正しくあなたの質問を理解しなかった場合、私はあなたがglobals()を使用して、このような何かを行うことができると思う。

class A: 
    pass 

class B: 
    pass 

class C: 
    pass 

def create_new_instances(classes): 
    for cls in classes: 
     name = '{}__'.format(cls.__name__) 
     obj = cls() 
     obj.__class__.__name__ = name 
     globals()[name] = obj 

if __name__ == '__main__': 
    classes = [A, B, C] 
    create_new_instances(classes) 
    classes_new = [globals()[k] for k in globals() if k.endswith('__') and not k.startswith('__')] 
    for cls in classes_new: 
     print(cls.__class__.__name__, repr(cls)) 

出力(あなたが同様の出力に含まを取得します):

A__ <__main__.A object at 0x7f7fac6905c0> 
C__ <__main__.C object at 0x7f7fac6906a0> 
B__ <__main__.B object at 0x7f7fac690630> 
+1

これは悪い答えではありませんが、私は助けてもいけませんが、これは非常に悪い考えであり、そのようなグローバルな名前空間を汚染していると思います。我々はこのようにOPが使用しようとしているインスタンスとクラスの数が分からないので... – Jason

+0

@Jasonそれは私がこの答えを書いたときに私の頭に来る最初のものです。答えはそれが必要かどうかを満たします。そうでなければあなたのコメントは正しいです。 –

2

あなたが言いますあなたが「クラスを格納する変数名をクラスの名前にする」ことを望んでいるが、それは非常に悪い考えである。変数名はデータではありません。名前はプログラマが使用するためのものであるため、コードを使用して生成する理由はほとんどありません。

代わりにインスタンスのリストを作成するか、クラス名でインデックスを作成することを確信している場合は、ディクショナリをインスタンスにマッピングするディクショナリを使用します。

私が何かお勧め:

list_of_instances = [cls() for cls in list_of_classes] 

またはこの:あなたが作成するコードを書いているとき、それは時々自動的に変数を生成するために意味を作ることができる稀な例

class_name_to_instance_mapping = {cls.__name__: cls() for cls in list_of_classes} 

一つでありますクラスオブジェクト自体を操作する(例えば、自動的にメソッドを生成するなど)。これは、少なくともプログラムで生成された名前がグローバル名前空間を汚染するのではなく、クラス名前空間に含まれるため、グローバル変数を作成するよりもやや簡単で難しいことです。

たとえば、標準ライブラリのクラスファクトリは、必要に応じてtupleのサブクラスを作成し、タプルの値に名前でアクセスできるようにする特別な記述子を属性として使用します。ここでは、その場で属性を操作するためにgetattrsetattrを使用して、自分で漠然と似た何かをすることができる方法の非常に粗製の例を以下に示します。

>>> T = my_named_tuple(['foo', 'bar']) 
>>> i = T(1, 2) 
>>> i.foo 
1 
>>> i.bar 
2 
+0

ありがとうBlckknight!問題は、後でこれらのクラスにアクセスできる必要があることです。私がlist_of_classesのclsのためのclass_name_to_instance_mapping = {str(cls):cls()}のようなことをすれば、class_name_to_instance_mapping ['ClassA']によってdictにアクセスすることはできません。 – mfvas

+0

ああ、私は私の例で不注意だったと思う。おそらく 'str(cls)'の代わりに 'cls .__ name__'が必要です。後者は、あまり便利ではないクラスのreprを取得します。私はより良い提案を与えるために答えを編集しました。クラス{{cls:cls()...}で名前を使わずにクラス自体からインスタンスにマップすることもできます。それはすべての中で最も便利かもしれません。 – Blckknght

関連する問題