• 締切済み

python __del__()に関して

「Programming Python 4th Edition」(O'REILLY) P.466に 以下のコードを実行すると 本来tmp.set(5)で6番目のRadiobuttonが選択された状態で初回表示されるはずだが radio1()終了時にtmp.__del__()が呼ばれて tmpに保持されている値がunsetされることにより Radiobuttonの初回表示が狂う (global行のコメントアウトをやめると正しく動作するようになる) といったことが書いてあり、実際にコードを実行すると確かにそのようになるのですが tmp.__del__()が呼び出される理由が理解できません。 __del__()が呼び出されるのはオブジェクトへの参照がなくなった時であって tmpの値(IntVarオブジェクト)はRadiobuttonのコンストラクタに渡されており、Radiobuttonオブジェクト内部で参照され続けるので、__del__()が呼ばれることはないはずだ、と素人考えでは思えるのですが。 お分かりになる方が居らっしゃればどうか教えて下さい。 ------------------------------------------------------------ from tkinter import * root = Tk() def radio1(): >>>>#global tmp >>>>tmp = IntVar() >>>>for i in range(10): >>>>>>>>rad = Radiobutton(root, text=str(i), value=i, variable=tmp) >>>>>>>>rad.pack(side=LEFT) >>>>tmp.set(5) radio1() root.mainloop() (>>>>は空白に読み替えてください)

みんなの回答

  • struct
  • ベストアンサー率72% (32/44)
回答No.2

tkinter のソースを読んでみるとよくわかると思いますが、 tkinter は Tcl/Tk という言語への橋渡しをしているに過ぎないんですよ。 Python で Tk() とか IntVar() とか書くたびに それが Tcl の命令に変換されて実行されるだけなんです。 例えば tmp = IntVar() を実行すると、 Tcl 側で PY_VAR1 という変数が作られます。 次に tmp がスコープを抜けると参照がゼロになるので GC が発動します。 その時に tmp.__del__ が呼ばれて Tcl 側にある PY_VAR1 を破棄します。 つまり tmp というのは Tcl 側に存在する変数を管理するオブジェクトなわけです。 そのオブジェクトの破棄イコール Tcl 変数の破棄になっているので 表示がおかしくなるわけです。 ちなみに、 > Radiobuttonのコンストラクタに渡されており、 > Radiobuttonオブジェクト内部で参照され続けるので... とありますが、Radiobuttonオブジェクトへの参照も ゼロになっていることを忘れていませんか? もっとも、Radiobuttonオブジェクトが破棄されても、 Tcl 側のラジオボタンを消すようにはなっていませんが。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

結論だけ簡単に書くと、variable=tmp によって tmp の参照数は増えていないので radio1() を抜けるところで tmp の寿命が尽きると判定されていて、結果 tmp.__del__ が 呼び出されるということになっています。 実装を事細かには書けないのですが、 >Radiobuttonオブジェクト内部で参照され続けるので この前提が間違っているということです。

HOKweb
質問者

お礼

ありがとうございます。 参照せずにどうやってRadiobuttonはIntVarの値を読み書きしてるのか想像つかないです。

関連するQ&A