15

モジュール内のクラスからインスタンス化されたオブジェクトがあるとします。次に、そのモジュールをリロードします。次にやりたいことは、リロードがそのクラスに影響するようにすることです。

mymodule.py
---
class ClassChange():
    def run(self):
        print 'one'

myexperiment.py
---
import mymodule
from mymodule import ClassChange  # why is this necessary?
myObject = ClassChange()
myObject.run()
>>> one
### later, i changed this file, so that it says print 'two'

reload(mymodule)
# trick to change myObject needed here
myObject.run()
>>> two

新しい ClassChange オブジェクトを作成し、そこに myObject をコピーして、古い myObject を削除する必要がありますか? それとももっと簡単な方法がありますか?

編集: run() メソッドは静的クラス スタイルのメソッドのように見えますが、これは簡潔にするためだけのものです。run() メソッドでオブジェクト内のデータを操作したいので、静的モジュール関数では実行できません...

4

7 に答える 7

6

新しいオブジェクトを作成する必要があります。既存のオブジェクトを魔法のように更新する方法はありません。

reload組み込みのドキュメントを読んでください-非常に明確です。最後の段落は次のとおりです。

モジュールがクラスのインスタンスをインスタンス化する場合、クラスを定義するモジュールを再ロードしても、インスタンスのメソッド定義には影響しません — それらは古いクラス定義を使用し続けます。派生クラスについても同様です。

ドキュメントには他にも注意事項があるため、実際に読んで代替案を検討する必要があります。なぜ使用したいのかという新しい質問を開始reloadし、同じことを達成する他の方法を尋ねたいと思うかもしれません。

于 2009-07-03T20:04:49.007 に答える
4

これに対する私のアプローチは次のとおりです。

  1. インポートされたすべてのモジュールを調べて、新しい .py ファイルを含むモジュールのみをリロードします (既存の .pyc ファイルと比較して)
  2. 再ロードされるすべての関数とクラス メソッドに対して、old_function.__code__ = new_function.__code__ を設定します。
  3. 再ロードされたクラスごとに、gc.get_referrers を使用してクラスのインスタンスを一覧表示し、それらの __class__ 属性を新しいバージョンに設定します。

このアプローチの利点は次のとおりです。

  • 通常、特定の順序でモジュールをリロードする必要はありません
  • 通常は、コードを変更してモジュールをリロードするだけで済みます。
  • インスタンスを追跡するためにクラスを変更する必要はありません

ここでテクニック (およびその制限) について読むことができます: http://luke-campagnola.blogspot.com/2010/12/easy-automated-reloading-in-python.html

コードはこちらからダウンロードできます: http://luke.campagnola.me/code/downloads/reload.py

于 2012-04-03T21:58:55.223 に答える
2

次のコードはあなたが望むことを行いますが、使用しないでください(少なくとも、正しいことを行っていることを確信するまでは使用しないでください) 。説明の目的でのみ投稿しています

mymodule.py:

class ClassChange():
    @classmethod
    def run(cls,instance):
        print 'one',id(instance)

私の実験.py:

import mymodule

myObject = mymodule.ClassChange()
mymodule.ClassChange.run(myObject)

# change mymodule.py here

reload(mymodule)
mymodule.ClassChange.run(myObject)

コード内でをインスタンス化するmyObjectと、 のインスタンスが取得されますClassChange。このインスタンスには、 というインスタンスメソッドrunがあります。リロードはクラス をリロードするだけなので、オブジェクトはリロードしてもこのインスタンスメソッドを保持します(noskloで説明されている理由により)ClassChange

上記のコードではrunクラス メソッドです。クラス メソッドは、インスタンスではなく、常にクラスにバインドされ、動作します (そのため、最初の引数は通常cls、 ではなくと呼ばれますself)。WennClassChangeがリロードされ、このクラス メソッドもリロードされます。

ClassChange の正しい (同じ) インスタンスを操作するために、インスタンスも引数として渡していることがわかります。どちらの場合も同じオブジェクト ID が出力されるため、これを見ることができます。

于 2009-07-03T20:24:14.230 に答える
1

やりたいことを叶えるコツがあります。

インスタンスのリストを保持するクラスを作成し、リロード時に各インスタンスのクラスを新しいクラスに変更できると誰かがすでに述べました。

ただし、それは効率的ではありません。より良い方法は、新しいクラスと同じになるように古いクラスを変更することです。

于 2009-07-04T01:38:04.993 に答える
1

これが最善の方法なのか、それともあなたがやりたいことと一致するのかはわかりませんが、これでうまくいくかもしれません。特定のタイプのすべてのオブジェクトに対してメソッドの動作を変更したい場合は、関数変数を使用してください。例えば:


def default_behavior(the_object):
  print "one"

def some_other_behavior(the_object):
  print "two"

class Foo(object):
  # Class variable: a function that has the behavior
  # (Takes an instance of a Foo as argument)
  behavior = default_behavior

  def __init__(self):
    print "Foo initialized"

  def method_that_changes_behavior(self):
    Foo.behavior(self)

if __name__ == "__main__":
  foo = Foo()
  foo.method_that_changes_behavior() # prints "one"
  Foo.behavior = some_other_behavior
  foo.method_that_changes_behavior() # prints "two"

  # OUTPUT
  # Foo initialized
  # one
  # two

モジュールのリロードを担当するクラスを作成し、リロード後Foo.behaviorに何か新しいものに設定できるようになりました。このコードを試しました。それは正常に動作します:-)。

これはうまくいきますか?

于 2009-07-03T20:26:21.763 に答える