[解決済み] 基本クラスから派生クラスを動的に作成する方法
質問
例えば、以下のようなベースクラスがあります。
class BaseClass(object):
def __init__(self, classtype):
self._type = classtype
このクラスから他のいくつかのクラスを派生させています。
class TestClass(BaseClass):
def __init__(self):
super(TestClass, self).__init__('Test')
class SpecialClass(BaseClass):
def __init__(self):
super(TestClass, self).__init__('Special')
新しいクラスを現在のスコープに置く関数呼び出しによって、これらのクラスを動的に作成するための素敵な、pythonicな方法はありますか、例えば。
foo(BaseClass, "My")
a = MyClass()
...
なぜこれが必要なのか、コメントや質問があることでしょう。派生クラスはすべてまったく同じ内部構造を持っていますが、違いはコンストラクタが以前に定義されていないいくつかの引数を取ることです。ですから、たとえば
MyClass
はキーワードを取ります。
a
クラスのコンストラクタは
TestClass
は
b
と
c
.
inst1 = MyClass(a=4)
inst2 = MyClass(a=5)
inst3 = TestClass(b=False, c = "test")
しかし、クラスの型を入力引数として使うことは決してあってはなりません。
inst1 = BaseClass(classtype = "My", a=4)
私はこれを動作させることができましたが、他の方法、すなわち、動的に作成されたクラスオブジェクトを希望します。
どのように解決するのですか?
このコードのビットを使用すると、新しいクラスを動的な
名前とパラメータ名を持つ新しいクラスを作成することができます。
でのパラメータ検証は
__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では良い習慣とは見なされていません。 変数名、またはデータ - そして実行時に学習した名前は、変数名"データ" よりも は、quot;変数"よりも "データ"です - 。
だから、クラスを辞書に追加して、そこから利用すればいいのです。
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:
この回答は人気がありましたが、質問本文に非常に特化しています。一般的な回答は
ベースクラスから派生クラスを動的に作成する方法に関する一般的な回答です。
を呼び出すだけです。
type
を呼び出すだけです。新しいクラスの名前、ベースクラスを含むタプル、そして
__dict__
のような新しいクラスのボディを渡します。
>>> new_class = type("NewClassName", (BaseClass,), {"new_method": lambda self: ...})
更新
これが必要な人は
ディル
プロジェクトもチェックしてみてください。これは、通常のオブジェクトに対して行うpickleのように、クラスのpickleとunpickleができると主張しており、私のテストのいくつかでそれを実行しました。
関連
-
[解決済み] Pythonで辞書に新しいキーを追加するにはどうすればよいですか?
-
[解決済み] 割り当て後にリストが予期せず変更されました。その理由と防止策を教えてください。
-
[解決済み] 列の値に基づいてDataFrameから行を選択するにはどうすればよいですか?
-
[解決済み] Windowsにpipをインストールするにはどうしたらいいですか?
-
[解決済み] Pythonの辞書からキーを削除するにはどうしたらいいですか?
-
[解決済み] リストからランダムに項目を選択するにはどうすればよいですか?
-
[解決済み] 派生クラス関数から親クラス関数を呼び出すには?
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み] PILからopenCVフォーマットへの変換
-
[解決済み] Pandasのデータフレーム内の文字列を'date'データ型に変換するにはどうしたらいいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Pythonでコード行間にかかる時間を測定するには?
-
[解決済み] pandasのタイムゾーンに対応したDateTimeIndexを、特定のタイムゾーンに対応したナイーブなタイムスタンプに変換する。
-
[解決済み] Ctrl-CでPythonスクリプトを終了できない
-
[解決済み] サブフォルダからのインポートモジュール
-
[解決済み] PyQtアプリケーションのスレッド化。QtスレッドとPythonスレッドのどちらを使うか?
-
[解決済み] Pythonで、ウェブサイトが404か200かを確認するためにurllibをどのように使用しますか?
-
[解決済み] 単純な文字列からtimedeltaオブジェクトを作成する方法
-
[解決済み] PythonのRequestsモジュールを使ってWebサイトに "ログイン "するには?
-
[解決済み] Pythonでリストが空かどうかをチェックする方法は?重複
-
[解決済み] Alembicアップグレードスクリプトでインサートやアップデートを実行するにはどうすればよいですか?