pythonのクラス内のリストの挙動
navyblue
navyblue
ATOMRSS
  • コード求むID: 345
  • 登録日時:  2008/11/16 11:13
  • 最終更新日時: 2008/11/17 23:46
  • アクセス数: 221
  • タグ:  python リスト クラス
  • codeなにがしブックマークに追加する 0 users
  • このページを del.icio.us に追加
  • このページをはてなブックマークに追加

プログラミングそのものをはじめたばかりの超初心者で、基本的な質問ですが、ご存知の方教えてください。

下記のソースで、KeyWordというクラスの実体を3つ作成しています(newKey1, newKey2, newKey3)。ここで期待しているのは、各実体で別々の値が入った変数、及びリストが出来上がっていることです。

すなわち、
newKey1 -> nmb=1, spl=['1']
newKey2 -> nmb=2, spl=['2']
newKey3 -> nmb=3, spl=['3']
と、生成するときの引数にしたがってそれぞれの実体の変数、リストが変わっている事です。

ところが、変数(nmb)については期待通りなのですが、リストについては新しい実体を作るとき、先に作った実体の中のリストに追加される結果となっています。
newKey1 -> nmb=1, spl=['1']
newKey2 -> nmb=2, spl=['1','2']
newKey3 -> nmb=3, spl=['1','2','3']
となっています。

私の理解では、クラスとはあくまで情報の持ち方の器であり、新しく実体が生成される際は、同じクラスでも先に作った実体とは無関係、と解釈していたのですが、根本的に何か間違っているのでしょうか。

よろしくお願いいたします。

ソース
--------------
print "**********************start************************"
####
class KeyWord:
  nmb=0     class内の変数
  spl=[]    class内のリスト
  def __init__(self,data):
    self.nmb=data       #引数をnmbに代入
    self.spl.append(data) #引数をリストに追加
####
keyWord=[]
newKey1=KeyWord("1")
newKey2=KeyWord("2")
newKey3=KeyWord("3")
print   ========   "
print "list",newKey1.spl
print "int ",newKey1.nmb
print "list",newKey2.spl
print "int ",newKey2.nmb
print "list",newKey3.spl
print "int ",newKey3.nmb
--------------

出力結果
--------------
['1']
['1', '2']
['1', '2', '3']
   ========   
list ['1', '2', '3']
int  1
list ['1', '2', '3']
int  2
list ['1', '2', '3']
int  3
--------------


コメント

Pythonのオブジェクトがらみの変数には、クラス変数とインスタンス変数の2種類があります。
クラス変数はそのクラスで器が共有される変数、インスタンス変数は実体(インスタンス)ごとに異なる器を持つ変数です。

class直下で変数に代入するとクラス変数になり、メソッド内で変数に代入するとインスタンス変数になります。

上のコードでは、class直下でnmbとsplに代入している部分で、クラス変数のnmbとsplが用意されます。
ただし、__init__内でself.nmbに代入していることにより、クラス変数のnmbとは別にインスタンス変数のnmbが作られ、dataの値が入ります。
一方、self.splは、代入ではなく参照されています。変数の参照なので、当然、すでにある変数が対象になります。そのため、クラス変数のsplの値が変化します。

その後、newKey1.nmbと参照した場合にはnewKey1のインスタンス変数が優先的に参照されます。
一方、newKey1.splは、newKey1にインスタンス変数splがないので、KeyWordのクラス変数splが参照されます。

GJ

emasakaさん

ありがとうございました。大変よくわかりました。
  nmb=0     
  spl=[]    
と書いている時点で、これらがクラス変数として取り扱われるのですね(そうとは知らず、特に意味もなく、宣言のつもりで記入していました)。

ところで、追加の質問があるのですが、このようにクラスの中でリストを取り扱うとき、たとえばこの例で言うと最初に上記
spl=[]
の記述がないと、
    self.spl.append(data)
でエラーになります。おそらく、splがリストであることを宣言(?)しないと
いけないような気がするのですが、そうするとこのコードのように、splが
クラス変数として取り扱われてしまいます。

このような場合、どうしたらよいのでしょう?

よろしくお願いいたします。

  • GoodJob
  • 0

おそらく、splがリストであることを宣言(?)しないと
いけないような気がするのですが、そうするとこのコードのように、splが
クラス変数として取り扱われてしまいます。
このような場合、どうしたらよいのでしょう?

メソッド定義の中に書けばインスタンス変数になります。

GJ

emasaka様

メソッドの中に書いたらうまくいきました。

  def __init__(self,data):
    self.spl=[]
    self.nmb=data
    self.spl.append(data)

何よりも、クラス変数とインスタンス変数の違いがよくわかりました。
ありがとうございました。

  • GoodJob
  • 0

前へ 1 次へ

コメントする

[block]から[/block]までの範囲はブロック表示されます。
部分的に目立たせたい時や、引用などにお使いください。

[code]から[/code]までの範囲は等幅表示されます。
ソースコードや設定ファイルの記述などにお使いください。

ゲスト投稿者:ゲスト:

関連ソースコード・ノウハウを登録

PDFLib | A library for processing PDF on the fly プレゼン公開・共有サイト handsOut.jp オープンタイプ株式会社 チーム・マイナス6% - みんなで止めよう温暖化

ブックマークコメント