[Python] super()

最近、以前hohehohe2さんから教えていただいた新スタイルのクラスに移行しています。
移行って言っても、object継承してるだけですが、、、


それに伴って、super()が使えるようになった模様です。
前にsuper使ったらなぜか使えなかったので、なんでだ、と思ってたんですが、謎が解けた。

今まではクラスの継承をする際、↓みたいな感じで書いてました。

class Klass2(Klass):
  def __init__(self):
    Klass.__init__(self)

(まぁこれが正しいのかも僕にはわからんのですが、たまたま見た本がそう書いてたのでこうやってました:P)

で、本題のsuperなんですが。

こちらを見る限り、第一引数には自分のクラスを突っ込んでいる様子。
これって、
>> super(Klass, self).xxx()
じゃなくて、
>> super(self.__class__, self).xxx()
ってやれたほうが楽なんですけど、ダメなんですかね。
出来れば固有名詞的なものは極力書きたくないんですが。

でもこれでやると多重継承した場合にどうなるんだろと思ったら、
いろいろ試したけど最初のやつしかアクセスできなくてアボン。
わかんねーーー。

とりあえず問題なさそうなら、
super(self.__class__, self).xxx()
のタイプを使おうと思います。

が、

hohehohe2さんのソースもそうなってはいなかったし、
何かそうしない理由があるのかなぁと思ったりもしています。

んんんんんんん、、、

「[Python] super()」への12件のフィードバック

  1. そう、固有名詞使いたくないんですよ。使っちゃったらsuperの意味ないやんって前から心の底で思ってました。

    > hohehohe2さんのソースもそうなってはいなかったし、
    > 何かそうしない理由があるのかなぁと思ったりもしています。

    わかりません!
    適当にやってました、ごめんなさい(__)

  2. >hohehohe2さん
    > そう、固有名詞使いたくないんですよ。使っちゃったらsuperの意味ないやんって前から心の底で思ってました。

    ですよね!
    や、正直どうなんだろうか、とウンウンうなってました。
    が、これで一安心です。ほっ。

  3. その書き方のクラスを2つ作って継承関係を
    作ると無限ループしますよ。

    #————————————————–
    # 無限ループ
    #————————————————–
    class A(object):
      def __init__(self):
        print(“create object by Class A –> start”)
        super(self.__class__, self).__init__()
        print(“create object by Class A start”)
        super(self.__class__, self).__init__()
        print(“create object by Class B <– end”)

    superclass = B()

  4. 貼り付けミス(?) orz
    #————————————————–
    # 無限ループ
    #————————————————–
    class A(object):
      def __init__(self):
        print(“create object by Class A –> start”)
        super(self.__class__, self).__init__()
        print(“create object by Class A start”)
        super(self.__class__, self).__init__()
        print(“create object by Class B <– end”)

    superclass = B()

  5. 貼り付けミスではないようですね。
    連続レスすみません。最後に私なりの解決策を…
    class A(object):
      __super = object
      def __init__(self):
        self.__super.__init__(self)

    class B(A):
      __super = A
      def __init__(self):
        self.__super.__init__(self)

  6. えぇ、すぐ気づきました。
    python3.xにはsuper()があることに、誠に申し訳ない…
    class A(object):
      def __init__(self):
        super().__init__()

    class B(A):
      def __init__(self):
        super().__init__()

    superclass = B()

  7. >パイソニアさん
    はじめまして。
    コメントありがとうございます。

    > 無限ループ
    げ、マジですか。
    クラスAとクラスBは同時に継承しててもまぁ別物だからいいだろうと思っていたのですが、そういうことでもないんですね。
    BからA行ってさらにObjectに登って、ということではないんですね。
    うーむ、、これはちょっと実際にテストしてみたいと思います。
    ありがとうございます。

    > 解決方法
    上の方の解決方法なんですが、__superに明示的に代入しているのは何でなんでしょうか?
    継承した時点でそうなるものだと思っていたのですがそうでもないってことですかね。

    Python3.xのはすっきりしてていいですね!
    そうそう、つまり書きたいのはこういうことなんです!

    そろそろPython3.xへの移行も考えたほうが良いんでしょうか。
    うーむ。

    諸々ありがとうございます(・・)ノシ

  8. >上の方の解決方法なんですが、__superに明示的に代入しているのは何でなんでしょうか?

    「継承後のselfからは、継承後の__class__しか取得できず、結局は継承後のsuperが取得される」ということです。だから継承後に上書きされない(にくい)__xxxという(プライベートな)変数名に代入しておいたのです。
    (上下に連続して書いてあるから、変更漏れは少ない)

    つまり、object->A->Bとした場合、Bのメソッド内で__class__を取得すると【B】、そのselfをそのまま渡したAのメソッド内でも__class__を取得するとやはり【B】、だからまた戻って…無限ループ…です。

    ちなみに、Python3.xからは、selfいらずの__class__が追加されましたので、この問題が解決しました。

  9. >パイソニアさん
    丁寧にありがとうございます。
    なるほど、、、そういうことなんですね。
    複数回の継承ってあまり行ったことが無いのでその辺全然意識してませんでした。

    Python3.0、アップデート内容がイマイチピンとこなかったのですが、そういう箇所にもメスが入っているんですね。

    諸々大変参考になりました!ありがとうございます!

  10. うーん、よく考えてから発言しないとだめですね、すみません。
    こういう問題があるようです。
    ttp://d.hatena.ne.jp/methane/20081227/1230400144

    対策として、メタクラスを使ってみました。
    この__superはclass直下では意味がありませんが、関数(メソッド)無いでは有効です。
    ttp://cybercrypt.nm.land.to/files/python/easy_super.py.txt

    パイソニスタになるにはまだ早いようです…

  11. >パイソニアさん
    すみません、僕の読みが完全に甘かったみたいです。
    時間出来てからじっくり追ってみたいと思います。
    まだまだPythonのPすら理解出来てないなぁ・・・。

    諸々ありがとうございます!時間が出来たら必ず全部じっくり目を通そうと思います。

  12. 6年前の記事に失礼します。
    Pythonのsuperに関して悩んでいたところ、こちらの記事が大変参考になったのでコメントさせていただきます。

    パイソニアさんの__superを下記のようにメソッドにしてsuper()を呼び出せば多重継承の場合も上手くいったのですが、いかがでしょうか。

    class A(object):
    def __init__(self):
    print ‘A’

    class B(A):
    def __init__(self):
    print ‘B’,
    self.__super().__init__()
    def __super(self):
    return super(B,self)

コメントを残す

メールアドレスが公開されることはありません。