[解決済み] 実行時にインスタンスの基底クラスを動的に変更するには?
質問
この記事
の使用法を示すスニペットがあります。
__bases__
を使って、既存のクラスコレクションにクラスを追加することで、Pythonコードの継承階層を動的に変更しています。 OK、これは読みにくいので、おそらくコードがより明確です。
class Friendly:
def hello(self):
print 'Hello'
class Person: pass
p = Person()
Person.__bases__ = (Friendly,)
p.hello() # prints "Hello"
ということです。
Person
を継承していないのです。
Friendly
を継承するのではなく、この継承関係は実行時に
__bases__
属性の変更により、実行時に動的に追加されます。 しかし、もし
Friendly
と
Person
を(object を継承して)新しいスタイルクラスとする場合、次のようなエラーが発生します。
TypeError: __bases__ assignment: 'Friendly' deallocator differs from 'object'
これに関して少しググってみると、どうやら はいくつかの非互換性を示しています。 を示唆しているようです。 具体的には 新スタイルのクラスオブジェクトは、その ベース 属性への割り当てをサポートしません。 .
質問ですが、上記の Friendly/Person の例を Python 2.7+ の新しいスタイルのクラスを使って動作させることは可能でしょうか。
__mro__
属性を使用することで可能でしょうか?
免責事項: 私は完全にこれは無名のコードであることを理解します。 これは純粋に思考実験であり、Python が多重継承に関連する問題をどのように扱うかについて何かを学ぶためのお遊びであることを、私は十分に理解しています。
どのように解決するのですか?
OK、もう一度言いますが、これは通常行うべきことではなく、情報提供のみを目的としたものです。
Pythonがインスタンスオブジェクトのどこでメソッドを探すかは
__mro__
属性によって決定されます (そのオブジェクトを定義するクラスの
M
メソッド
R
解決方法
O
rder 属性)。 したがって、もし私たちが
__mro__
の
Person
のようにすれば、望ましい動作が得られるでしょう。 こんな感じ。
setattr(Person, '__mro__', (Person, Friendly, object))
問題なのは
__mro__
が読み取り専用の属性であるため、setattr が動作しないことです。 Python の第一人者であれば、それを回避する方法があるかもしれませんが、明らかに私は第一人者には程遠いので、それを思いつきません。
可能な回避策は、単にクラスを再定義することです。
def modify_Person_to_be_friendly():
# so that we're modifying the global identifier 'Person'
global Person
# now just redefine the class using type(), specifying that the new
# class should inherit from Friendly and have all attributes from
# our old Person class
Person = type('Person', (Friendly,), dict(Person.__dict__))
def main():
modify_Person_to_be_friendly()
p = Person()
p.hello() # works!
これは、以前に作成した
Person
インスタンスに
hello()
メソッドを使用します。 例えば、(単に
main()
):
def main():
oldperson = Person()
ModifyPersonToBeFriendly()
p = Person()
p.hello()
# works! But:
oldperson.hello()
# does not
の詳細が不明な場合は
type
の呼び出しの詳細が明確でない場合は、次のように読んでください。
e-satis's excellent answer on 'What is a metaclass in Python?'(Pythonのメタクラスとは何か?
.
関連
-
[解決済み] Pythonでシングルトンを作成する
-
[解決済み] 億の相対的輸入
-
[解決済み] mixinとは何か、なぜ有用なのか?
-
[解決済み] Pythonのsuper()は多重継承でどう動くのか?
-
[解決済み] XMLを解析して、特定のノード属性のインスタンスをカウントするには?
-
[解決済み] ベースクラスのコンストラクタを呼び出す際のルールは?
-
[解決済み] print()を使用してクラスのインスタンスを表示するには?
-
[解決済み] 与えられたクラスの階層にあるすべてのベースクラスをリストアップしますか?
-
[解決済み] Jupyterノートブックでenv変数を設定する方法
-
[解決済み] Pythonで、ウェブサイトが404か200かを確認するためにurllibをどのように使用しますか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] XHTMLの自己完結型タグを除くオープンタグにマッチするRegEx
-
[解決済み] Pythonです。未束縛のメソッドを束縛する?
-
[解決済み] Flaskで1時間ごとに関数を実行するようにスケジュールするには?
-
[解決済み] Pythonでコード行間にかかる時間を測定するには?
-
[解決済み] 古いバージョンのPythonにおける辞書のキーの並び順
-
[解決済み] tensorflowのCPUのみのインストールでダイナミックライブラリ 'cudart64_101.dll' を読み込めなかった
-
[解決済み] Pandasのデータフレーム内の文字列を'date'データ型に変換するにはどうしたらいいですか?
-
[解決済み] pycharmがタブをスペースに自動変換する
-
[解決済み] Pythonの検索パスを他のソースに展開する
-
[解決済み] Pythonの文字列書式をリストで使う