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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

3回答

503閲覧

classの中の、整数と文字を一緒にアウトプットするメソッドの記述について

okahijiki

総合スコア404

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2023/01/29 02:31

以下のclassについて質問します。
目標は、横✕高さ✕奥行きにて体積を求め、単位のcmを付けることです。

以下、Classを作成した後、インスタンスを変数に入れ、cm付きの体積をアウトプットするメソッドunit_content()を呼び出すと、「dが定義されていません」というエラーメッセージが出てしまいます。

python

1class Prism: 2 def __init__(self,width,height,depth,unit='cm'): 3 self.width = width 4 self.height = height 5 self.depth = depth 6 self.unit = unit 7 8 def content(self): 9 d = self.width*self.height*self.depth 10 11 def unit_content(self): 12 return d+self.unit 13 14#6000cmという値が出力されることを期待 15prism=Prism(10,20,30) 16prism.unit_content() 17 18#NameError: name 'd' is not defined

◎やったこと

そもそも、__init__メソッドの引数4つに対して、インスタンスを作成するときの引数が3つになっています。なので、以下のClass を試してみました。

python

1class Prism: 2 def __init__(self,width,height,depth,number): 3 self.width = width 4 self.height = height 5 self.depth = depth 6 self.number = number 7 8 def content(self): 9 d = self.width*self.height*self.depth 10 11 def unit_content(self): 12 return d+self.number 13 14#6003という値が出力されることを期待 15prism=Prism(10,20,30,3) 16prism.contentPlusNumber() 17 18#NameError: name 'd' is not defined 19

ちなみに、以下のようなclassを書くとエラーなしで表示されるので、インスタンス変数の積を変数に代入する、d = self.widthself.heightself.depthという記述には問題がないようです。

python

1class Prism: 2 def __init__(self,width,height,depth): 3 self.width = width 4 self.height = height 5 self.depth = depth 6 7 def content(self): 8 d = self.width*self.height*self.depth 9 return d 10 11prism=Prism(10,20,30) 12prism.content() 13 14#6000

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

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

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

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

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

maisumakun

2023/01/29 02:34 編集

> unit_content()を呼び出すと、「dが定義されていません」というエラーメッセージが出てしまいます。 どうしたいのですか?(動作だけでなく、どのようなコードにしたいのかも明記してください)
guest

回答3

0

いろいろ基本的なpythonの知識が足りないように思いますが、ちょっと説明します。

__init__メソッドの引数4つに対して、インスタンスを作成するときの引数が3つになっています。

これは問題ではありません。 __init__の定義のときに、4つめの変数にはデフォルトの引数"cm"が定義されているからです。

python

1def __init__(self,width,height,depth,unit='cm'):

このように定義したとき、引数が省略された場合はデフォルトの値が使われます。

「dが定義されていません」というエラーメッセージが出てしまいます
d = self.widthself.heightself.depthという記述には問題がない

pythonの(他の言語でもたいていそうですが)変数は、通常その関数/メソッドの中でしか有効ではありません。

python

1 def content(self): 2 d = self.width*self.height*self.depth 3 4 def unit_content(self): 5 return d+self.unit

contentメソッドでdに値を入れているつもりなのだと思いますが、このときのdはcontentメソッドが終了したときに消えてしまいます。 なので、 unit_content関数で使おうと思っても使えないのです。
contentメソッドで作った値を使いたいのであれば、meilianさんの回答のようにdの値を返すようにしてunit_contentで呼ぶようにするか、__init__でやっているようにインスタンスに保存するかです。

python

1 def content(self): 2 self.d = self.width*self.height*self.depth 3 4 def unit_content(self): 5 return str(self.d)+self.unit

こうやって、contentメソッドの中で self.d として代入することで、インスタンスのdに保存することができ、別のメソッドからも self.d で呼ぶことができるようになります。
__init__でやっていることと同じですね。 __init__が特別なわけではないのです。

ただし、このようにした場合、実際に使うときは、contentメソッドを明示的に呼んでやらないとdの値が設定されません。
なので、修正後のコードも書くと、

python

1class Prism: 2 def __init__(self,width,height,depth,unit='cm'): 3 self.width = width 4 self.height = height 5 self.depth = depth 6 self.unit = unit 7 8 def content(self): 9 self.d = self.width*self.height*self.depth 10 11 def unit_content(self): 12 return str(self.d) + self.unit 13 14prism=Prism(10,20,30) 15prism.content() 16prism.unit_content()

contentを途中で呼ばなければならないのは面倒なので、僕なら__init__の中で体積は計算してしまいますね。

python

1class Prism: 2 def __init__(self,width,height,depth,unit='cm'): 3 self.width = width 4 self.height = height 5 self.depth = depth 6 self.unit = unit 7 self.volume = self.width * self.height * self.depth 8 9 def unit_content(self): 10 return str(self.volume) + self.unit 11 12prism=Prism(10,20,30) 13prism.unit_content()

投稿2023/01/29 03:21

TakaiY

総合スコア12743

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

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

okahijiki

2023/01/29 03:29

ご教示いただいた記述なら(僕にとって)直感的に分かります〜。ありがとうございます!
okahijiki

2023/01/29 07:19

解説、理解の糧になります。ありがとうございます。 こういうふうに解釈しました。間違ってないでしょうか。 確認のため、ご回答の内容と重なることご容赦くださいませ。 ①__init__にて引数(このばあいuinit=‘cm)を定義し、 ②インスタンスを作成し変数に代入する際に、その引数を省略したばあい、 デフォルト値(このばあい’cm’)が代入される。 2)基本的にClass内のメソッドの利用は1回限り。 ただし、 d=self.width * self.height * self .depthではなく、 self.d = self.width * self.height * self .depthとすれば、 インスタンスを作成し変数に代入するときself.dは保持され、その限りではない。
TakaiY

2023/01/29 08:28 編集

1) あっていますが、これは__init__に限らず、すべての関数/メソッドの定義時の機能です。 公式だと、 以下のページの少し下に説明があります。 https://docs.python.org/ja/3/reference/compound_stmts.html#function-definitions 1 つ以上の 仮引数 が parameter = expression の形を取っているとき、関数は "デフォルト引数値" を持つと言います。デフォルト値を持つ仮引数では、呼び出し時にそれに対応する 実引数 は省略でき、その場合は仮引数のデフォルト値が使われます。 2) > 基本的にClass内のメソッドの利用は1回限り。 そんなことはありません。 どうしてそういう理解になったのでしょう? あ、もしかして、「メソッド」ではなく「変数」のことですか? そして、「1回限り」ではなく「その場限り」ですかね。であれば合っています。 クラス内に限らず、単にdとした場合のような、関数/メソッド内の変数はその関数内のローカル変数であり、関数の外からはアクセスすることはできませんし、関数の実行が終ると消えてしまいます。 クラスのメソッドでは、インスタンスにメソッドの第一引数(通常selfと書きます)でアクセスできて、インスタンス固有の変数(ここではd)を self.d のような書き方で作って値を設定することができます。 これは、インスタンスが存在する間はずっと存在していて、他のメソッドや外部からアクセスすることができます。 なので、self.d と d は根本的に違うものだと思っていいです。
guest

0

次のようなクラス定義にしてはいかがでしょう?

python3

1class Prism: 2 def __init__(self, width, height, depth, unit): 3 self.__width = width 4 self.__height = height 5 self.__depth = depth 6 self.__unit = unit 7 self.__volume = width * height * depth 8 9 def volume(self): 10 return self.__volume 11 12 def volume_with_unit(self): 13 return f"{self.__volume}{self.__unit}" 14 15 16# 6003という値が出力されることを期待 17prism = Prism(10, 20, 30, 3) 18print(prism.volume()) 19print(prism.volume_with_unit()) 20# => 60003 21 22prism = Prism(10, 20, 30, " cm3") 23print(prism.volume()) 24print(prism.volume_with_unit()) 25# => 6000 cm3 26 27# print(prism.__width) # これはエラーになる

一度生成した prism の width, heigjt, depth を後から変更することを禁止できます。
体積の計算も init 処理中で1度 実行するだけです。

投稿2023/01/29 04:06

katoy

総合スコア22324

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

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

0

ベストアンサー

python

1class Prism: 2 def __init__(self,width,height,depth,unit='cm'): 3 self.width = width 4 self.height = height 5 self.depth = depth 6 self.unit = unit 7 8 def content(self): 9 return self.width*self.height*self.depth 10 11 def unit_content(self): 12 return str(self.content()) + self.unit 13 14if __name__ == '__main__': 15 prism = Prism(10,20,30) 16 print(prism.unit_content())

投稿2023/01/29 02:40

melian

総合スコア19703

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

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

okahijiki

2023/01/29 02:49

ご回答ありがとうございます。int+strになっていたので、intをstr()にてstrに統一させた..そこまでは理解できすのですが、 def unit_content(self): return str(self.content()) + self.unit にて、content( )メソッドにselfを付けて、self.content()とする記述が、初学者の僕にとって、直感的に分かりずらい部分であったりします。「どこが分かりづらいのか」というと、ごめんなさい、ちょっと言葉で説明できません。もっと学習する必要がありそうです〜
melian

2023/01/29 02:55

単純にインスタンスメソッドを呼び出しているだけになります。ここを直感的に理解してしまうと後々マズいことになりかねないので、できるだけ「論理的に」理解できる様に学習を進めてみて下さい。
okahijiki

2023/01/29 03:03

ちなみに、以下の記述でも、うまくいきました。 d = self.width*self.height*self.depthとし、dをunit_content()にて返すところに、どうやらムリがあるような感触を持ちました。ご報告にて、失礼します〜 class Prism: def __init__(self,width,height,depth,unit='cm'): self.width = width self.height = height self.depth = depth self.unit = unit def unit_content(self): return str(self.width*self.height*self.depth) + self.unit if __name__ == '__main__': prism = Prism(10,20,30) print(prism.unit_content()) #6000cm
melian

2023/01/29 03:05 編集

※ 入れ違いのため削除
okahijiki

2023/01/29 07:33

ご回答ありがとうございます。初期メソッドのunitに値を設定せず、文字列に統一して出力...といった感じでしょうか。いろいろな書き方があって。参考になります〜
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問