このコードにより、動的な名前とパラメーター名を使用して新しいクラスを作成できます。のパラメーター検証で__init__
は、不明なパラメーターは許可されません。タイプなどの他の検証が必要な場合、またはそれらが必須である場合は、そこにロジックを追加するだけです。
class BaseClass(object):
def __init__(self, classtype):
self._type = classtype
def ClassFactory(name, argnames, BaseClass=BaseClass):
def __init__(self, **kwargs):
for key, value in kwargs.items():
# here, the argnames variable is the one passed to the
# ClassFactory call
if key not in argnames:
raise TypeError("Argument %s not valid for %s"
% (key, self.__class__.__name__))
setattr(self, key, value)
BaseClass.__init__(self, name[:-len("Class")])
newclass = type(name, (BaseClass,),{"__init__": __init__})
return newclass
そして、これはこのように機能します、例えば:
>>> SpecialClass = ClassFactory("SpecialClass", "a b c".split())
>>> s = SpecialClass(a=2)
>>> s.a
2
>>> s2 = SpecialClass(d=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __init__
TypeError: Argument d not valid for SpecialClass
動的な名前を名前付けスコープに挿入することを求めているようです-今では、これはPythonの良い習慣とは見なされていません-コーディング時に既知の変数名またはデータがあり、ランタイムで学習した名前はより多くなります「変数」より「データ」-
したがって、クラスをディクショナリに追加して、そこから使用することができます。
name = "SpecialClass"
classes = {}
classes[name] = ClassFactory(name, params)
instance = classes[name](...)
そして、もしあなたのデザインが絶対に名前をスコープに入れる必要があるなら、同じことをしてください、しかしglobals()
任意の辞書の代わりに呼び出しによって返された辞書を使用してください:
name = "SpecialClass"
globals()[name] = ClassFactory(name, params)
instance = SpecialClass(...)
(確かに、クラスファクトリ関数が呼び出し元のグローバルスコープに動的に名前を挿入することは可能ですが、これはさらに悪い習慣であり、Python実装間で互換性がありません。これを行う方法は、呼び出し元のsys._getframe(1)を介して実行フレームを作成し、そのf_globals
属性でフレームのグローバルディクショナリのクラス名を設定します。
update、tl; dr:この回答は一般的になりましたが、それでも質問本体に非常に固有です。
Pythonで「基本クラスから派生クラスを動的に作成する」方法に関する一般的な答えは、次のように
type
、新しいクラス名、ベースクラスを含むタプル、および__dict__
新しいクラスの本体を渡す簡単な呼び出しです。
>>> new_class = type("NewClassName", (BaseClass,), {"new_method": lambda self: ...})
更新
これを必要とする誰もがもチェックする必要がありディルのプロジェクトを-それは酸洗いすることができると主張化したりunpickle化したり、クラスピクルスは、通常のオブジェクトにないと同じように、そして私のテストのいくつかで、それまで住んでいました。
a
それは常にありMyClass
、TestClass
決してかかりませんa
?3つの引数をすべて宣言するだけでBaseClass.__init__()
なく、デフォルトですべてに設定するのはなぜNone
ですか?def __init__(self, a=None, b=None, C=None)
?