質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

5583閲覧

pythonのクラス継承 selfやlist、インステンスとは

torano

総合スコア92

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2016/01/01 09:18

編集2016/01/02 10:36

プログラミング始めたばっかの初心者です。
以下のコードでわからない点がありました。

class Deck(list): def __init__(self): list.__init__(self) def make_card(self, name, power): return {name:power} def add_card(self, name, power): self.append(self.make_card(name, power) ) def print_deck(self): print "all card num:", len(self) for card in self: print card if __name__ == "__main__": t = Deck() for i in xrange(1, 10): t.add_card("card no."+str(i), i * 4 + 10) t.print_deck()

疑問点は3つです。公式ドキュメントを見てみたりしたのですが難しくてあまり理解できませんでした。初心者にもわかるように教えてもらえないでしょうか。よろしくお願いします。

1、継承元がlistだと思うのですが、具体的に定義されてないですし、print listなどとしても表示されないですし、これはなんなのでしょうか?変数ではないんですか?

2、selfってクラス関数の第一引数だからインスタンスを代入されたtの事だと思うのですが、7、10行目を見るとどうやらリストになっているみたいでよくわかりません。インスタンスの定義もそもそもよくわかっていないです。

3、上記のコードの7、9、10行目のselfをlistに置き換えても失敗するのはどうしてでしょう?下記のコードではうまくいっていますが違いがわかりません。また逆に下記のコードでlistをselfに置き換えてもうまくいきません。

# -*- coding: utf-8 -*- class TestExtends(list): def __init__(self): list.__init__(self) def append(self,value): list.append(self,value) print u"値が追加されました:" + str(value) if __name__ == "__main__": test = TestExtends() test.append("python") test.append("-") test.append("izm") print "===============" for i in test: print i

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

質問3は TestExtends のケースと似ているのになぜ違うかということかと思います。

Deckクラスの append は継承しているlist のappend を呼び出す必要があります。
Deckクラスには独自の append はないので、 self.append で list のappend が呼ばれます。

これに対し、TestExtends クラスには 継承しているlist のappend とは別の TestExtends 独自の appned が定義されているため、ここで
def append(self,value):
self.append(value)
としてしまうと、自分(TestExtends)のappendが呼び出されておかしなことになってしまいます。

Deckクラスの add_card を list を使って書き換えるなら以下のようになります。
def add_card(self, name, power):
list.append(self,self.make_card(name, power) )

また、TestExtends クラスを self を使って書き換えるなら以下のようになります。
上で説明したように append の名前が重なっているため append を myappend として

def myappend(self,value): self.append(value)

呼び出す方は
test.myappend("python")
のような形になります。

投稿2016/01/01 13:05

yoshi777

総合スコア674

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

torano

2016/01/02 10:21

Deckクラスを以下のように変えてうまくいくのはわかったのですが def add_card(self, name, power): list.append(self,self.make_card(name, power) ) これに加えて9、10行目のselfもlistに変えるとうまくいかないのは何故なのでしょう?
yoshi777

2016/01/02 14:25

9,10行目はインスタンスを表しているので、self にする必要があります。 例えば len(self) は self(ここではt)の要素数であり、list の要素数ではありません。
torano

2016/01/03 04:18

list.append(self,self.make_card(name, power) )はselfに要素を追加しているということですか?
yoshi777

2016/01/03 06:54

そうです。 list.append(self,xx .. は self.append(xx... と同じなので。 この部分は9,10行目の話とは違って、tanaga さんが「メソッドオブジェクト」で説明されている話です。
torano

2016/01/03 09:00

なるほど!理解できました、ありがとうございます
guest

0

予約語以外は変数です。listも(ビルトイン)変数です。
問題は、変数は何でも入るので、今その変数に何が入っているのかを把握することが重要です。

1、継承元がlistだと思うのですが、... 変数ではないんですか?

変数ですが、中に入っている型が重要です。listは標準でクラスが入っている変数ですね。

2、selfってクラス関数の第一引数だからインスタンスを代入されたtの事だと思うのですが

その通りです

7、10行目を見るとどうやらリストになっているみたいでよくわかりません。

クラスを"棒のハンコ"、インスタンスをそれを"紙に押したハンコ"と思ってください。
どちらも「ハンコ」なのでわかりづらいですね。listも同じです。

3、上記のコードの7、9、10行目のselfをlistに置き換えても失敗するのはどうしてでしょう?

「"紙に押したハンコ"を"棒のハンコ"に置き換えたら動きません」当たり前ですね。

下記のコードではうまくいっていますが違いがありません。また逆に下記のコードでlistをselfに置き換えてもうまくいきません。

ここがPythonのややこしいところです。以下の文章が参考になるでしょう。
Pythonは初期はクラスを持っておらず、後から追加した際にこのような仕様で「吸収」した経緯があります。

9.3.4. メソッドオブジェクト

x = MyClass() ... (中略) ... x.f() という呼び出しは、 MyClass.f(x) と厳密に等価なものです。

ただし、実際には「MyClass.f(x)」ではなく「x.f()」のほうが良いでしょう。
なぜなら、後からMyClassではなくYourClassに変えたくなった時に、最初の1箇所だけ変えれば良いためです(別のやり方だと2箇所変えなくてはならないし、YourClassがMyClassを継承している場合は忘れる可能性が非常に高いし、忘れたことに気づきにくい)。

投稿2016/01/01 12:02

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

torano

2016/01/02 10:37 編集

x = MyClass() ... (中略) ... x.f() という呼び出しは、 MyClass.f(x) と厳密に等価なものです。 とありますが、この文のxをself、MyClassをlistに置き換えたもの(つまりself.f()とlist.f(self)が同値)という解釈でおkでしょうか?
torano

2016/01/02 10:29

もう一つ、listがリストクラス、selfがインスタンスだという認識だったのですが、もしかしてselfはリストクラスでもあるんですか?例えば x=[] x.append(3) とするとリストクラスxに要素3が追加されますが、最初に紹介したコードのDeckクラスでも self.append(self.make_card(name, power) )と同じようになってますよね。(逆にlistではこれと同じように書くとうまくいきません) 理解できてきたと思ったらまたこんがらがってきました...
退会済みユーザー

退会済みユーザー

2016/01/02 12:14

> listがリストクラス、selfがインスタンスだという認識だったのですが あっていますね。listがリストクラス、selfがリストインスタンスですね。 もしJavaをご存知なら、もう少し話は簡単です。 Javaのインスタンスメソッド内で自分自身を参照するときは、thisを使います。thisはシステムが用意してくれる変数です。 Pythonにはthisがありません。これは、Pythonの初期の設計にはクラスの機能が無かったからです。Pythonの作者はPythonに後からクラスの機能を追加するときに、thisをシステムで用意せず、インスタンスメソッドの第1引数に自分自身(this相当)を用意することにし(てなんとかごまかし)ました。 第1引数の名前はなんでもいいのですが、多くの人がselfにしているのでそのようにしましょう。 上記の経緯から、インスタンスメソッドを呼び出す方法が2種類ほどできてしまったわけです。この説明でわからない場合は、少し間を置いて見なおすか、もっとじっくり公式文章を読むべきです。
torano

2016/01/02 13:58

コーディングはpythonが初めてで。。。 じっくりドキュメントを見直してみます ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問