1

Canvasをコンテナとして使用することについて巧妙な質問をしたかったのですが、サンプルコードを書くと、何か奇妙なことに出くわしました。これまでのコードは次のとおりです。

import Tkinter as tk

class CCanvas(tk.Canvas):

    def __init__(self,master,*args,**kwargs):
        super(CCanvas,self).__init__(master=master,*args,**kwargs)


if __name__ == '__main__':
    root= tk.Tk()
    cc = CCanvas(root)
    cc.pack()
    root.mainloop()

今、このコードはあまり役に立たないはずです。CCanvasクラスはCanvasから継承するだけで、何も実装せず、スーパークラスのコンストラクターを呼び出すだけです。これが機能しない理由はわかりません。しかし、これを実行すると、次のエラーが発生します。

super(CCanvas,self).__init__(master=master,*args,**kwargs)
TypeError: must be type, not classobj

誰かが私にこの振る舞いを説明し、多分それを修正する方法を教えてもらえますか?

4

1 に答える 1

6

ここでの問題は、TkInterクラス(2.x)が古いスタイルのクラスであるということです。違いはデータモデルのドキュメントで詳細に説明されていますが、これについての詳細を知る必要はありません。知っておく必要があるのは、使用できないことですsuper(そして、明示的に呼び出すことでそれを回避する方法__init__)。そして、Steven Rumbalskiが指摘しているように、 super()はエラーで失敗します。TypeError「引数1はclassobjではなくtypeである必要があります」</a>は、しようとしている基本クラスが古い場合にこのエラーメッセージが表示される理由を説明していますsuperスタイルのクラス。

これはドキュメントに記載されておらず、探しに行かない限りわかりませんが、2つを区別する方法を知っていれば、それほど難しくはありません。

python-listのスレッドで指摘されているように、これは通常問題ではありません。新しいスタイルのクラスの動作が必要な場合は、いつでも実行できるからですclass CCanvas(tk.Canvas, object):

しかし、気にしないことがいくつかあり、そのうちの1つはsuper基本クラスへの能力です。代わりに、昔ながらの方法で基本クラスを名前で明示的に参照する必要があります(つまり、self明示的に渡す必要があります)。

def __init__(self,master,*args,**kwargs):
    TkInter.Canvas.__init__(self, master=master, *args, **kwargs)

(もちろん、別の解決策は、古いスタイルのクラスがないPython 3にすでに移行することです…)

(完全を期すために、super古いスタイルのクラスで90%を偽造することは可能であり、2.xの初期にはいくつかのレシピが浮かんでいました…しかし、あなたはそれをしたくありません。)

于 2013-01-17T23:33:35.667 に答える