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

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

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

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

Q&A

解決済

2回答

998閲覧

クラスのインスタンスを利用した関数の定義

Qiitahana

総合スコア4

Python

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

0グッド

0クリップ

投稿2021/11/17 08:36

編集2021/11/18 07:20

前提・実現したいこと

スクールの課題です。
以下のクラスを定義しています。

class Person(object): def __init__(self, name, age, gender): self._name = name self._age = age self._gender = gender self._friend = None def __eq__(self, person): return str(self) == str(person) def __str__(self): if self._gender == 'M': title = 'Mr' elif self._gender == 'F': title = 'Miss' else: title = 'Ms' return title + ' ' + self._name + ' ' + str(self._age) def __repr__(self): return 'Person: ' + str(self) def get_name(self): return self._name def get_age(self): return self._age def get_gender(self): return self._gender def set_friend(self, friend): self._friend = friend def get_friend(self): return self._friend

クラスの「外部で」、インスタンスの「名前」、「年齢」、友人がいる場合「友人」の属性をプリントする
関数を定義する必要があります。

発生している問題・エラーメッセージ

このように関数を書きました。

def print_friend_info(person): n = person.get_name() a = person.get_age() fr = person.get_friend() print(n) print(a) if fr: fr_is = fr._name print(f'Friends with {fr_is}')

しかし、「友人」を書き出すパートのみなぜか上手く認識されません。
if fr: 以降が該当箇所なのですが、何か穴等ありますでしょうか?(カバーできていないパターン等)

該当のソースコード

python

試したこと

こちらのコードも試しました。同じく、「友人」を書き出すパートのみ認識されません。

def print_friend_info(person): print(person._name) print(person._age) fr = person.get_friend() if fr: print(f"Friends with {fr._name}")

微妙に違う文法で何通りか試してみましたが、どれも同じく「友人」を書き出すパートのみ駄目でした。

補足情報(FW/ツールのバージョンなど)

バージョン: python3.9
IDE: IDLE(Python3.9 64-bit)

関数はクラスとは独立しており、また上記のコード以外の呼び出しコードや枠組み等といったものは使用しておりません。
自分の書いたprint_friend_info関数でカバーできていないシチュエーションがあれば教えてください。
(インプットは正しいという前提で)

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

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

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

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

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

BeatStar

2021/11/17 08:40

コードは"<code>"または"<コード>"のボタンを押して出てくるやつの中に書きましょう。 今のままでは読みづらいです。 それにPythonはインデントが意味を持ちます。 質問は編集できるので編集してください。それからです。
BeatStar

2021/11/17 08:43

それと、コードはすべて提示してください。少なくともprint_friend_info関数とやらを呼び出している場所があるはずです。 ということはこのコードは中途半端な状態ってことです。それで回答はできません。
TakaiY

2021/11/17 12:38

「「友人」を書き出すパートのみ認識されません。」とか、 「友人」を書き出すパートのみ駄目」とは具体的にどうだめですか。 また、上の方も書いているように、その問題が発生したときのコードも提示してください。 単に、友人を設定していないだけなんじゃないかと思ってますが。
Qiitahana

2021/11/18 07:21

>>>BeatStarさん 今投稿を確認してみたところ、何故かインデントが全解除されていたようですので コードを一から書き直してみました。ご指摘ありがとうございます。 print_friend_info関数はクラスとは独立した関数であり、またクラスの定義とこちらの関数で コードは全てになります。(そのため、関数が呼び出されていなかった等の問題は発生するとは思いません) >>>TakaiYさん 「友人」をset_friend(friend)メソッドにて設定し、print_friend_info関数で書きだすと確かに友人にあたるインスタンスの名前が書きだされ、設定していないと何も表示されない、と自分では正常に作動しているように見えるのですが、それでも認識されません。 また、今コードを再度書き直して実行してみたところ、「名前」、「年齢」、「友人」情報の全てが認識されなくなっていました…。自分の書いた関数のコード内に、何か穴等はありますか?というのが質問です。 こういうパターンに対応できていない、こういう時にクラッシュするというパターンがあれば教えてください。 インプットの形は正しい(クラス型である)という前提は成り立つと思われます。
ozwk

2021/11/18 07:39

>またクラスの定義とこちらの関数でコードは全てになります。(そのため、関数が呼び出されていなかった等の問題は発生するとは思いません) これで全てだったらprint_friend_infoを呼んでいる部分がないでしょう。
TakaiY

2021/11/18 07:42

「「友人」をset_friend(friend)メソッドにて設定し、print_friend_info関数で書きだすと確かに友人にあたるインスタンスの名前が書きだされ、設定していないと何も表示されない、と自分では正常に作動しているように見える」 のであれば、全く正常に思えます。が、「それでも認識されません」ですか。 あなたの言う「認識され」るとはどういうことを想定していますか? また、BeatStarさんへの回答に「こちらの関数でコードは全てになります。」とありますが、これでは定義のみしかないので、クラスはインスタンスが作られず、関数も呼ばれませんから、何も起きませんよ。 「実行」したときのコードも提示してください。
Qiitahana

2021/11/20 13:46 編集

お返事遅くなってしまってすみません。 >>>ozwkさん 後ほど個別に、set_friendを用いてインスタンスにfriendを持たせ、print_friend_infoを呼び出すという作業を行っています。 >>>TakaiYさん 自分では、以下の様に実行しています。 a = Person("A", 10, "M") b = Person("B", 15, "F") a.set_friend(b) print_friend_info(a) <出力: A 10 Friends with B> print_friend_info(b) <出力: B 15> このprint_friend_info関数自体なのですが、例えばこういう入力があったらコードがクラッシュするとか、こういうケースがカバーできていないとか欠陥がありますでしょうか? よろしければご指摘ください。
TakaiY

2021/11/20 14:26 編集

> 例えばこういう入力があったらコードがクラッシュするとか、こういうケースがカバーできていないとか欠陥がありますでしょうか? それは、このプログラムをどのように使うかによりますから、こちらからは何とも言えませんよ。 たとば、set_friendで設定するオブジェクトが_name属性を持っていなければ落ちますが、それを保証するのがどれなのかは設計によります。 また、途中で 「fr_is = fr._name」このように使っていますが、ここはget_nameを使うべきだろうとかも気になりますね。 何を心配しているのかよくわかりません。 あと、もう一度聞きますが、あなたの言う「認識され」るとはどういうことを想定していますか?
ozwk

2021/11/20 22:50

>後ほど個別に、 それをどう書いているかを提示してください
Qiitahana

2021/11/21 02:23 編集

>>>TakaiYさん >途中で 「fr_is = fr._name」このように使っていますが、ここはget_nameを使うべきだろうとかも気になります こちら修正してコードを実行してみたところ、正しく動きました。 >あなたの言う「認識され」るとはどういうことを想定していますか プライベートアトリビュートに直接アクセスしたら上手く動かない、という事だったようなのです。 (一人でやっているコーディングではなかったのですが、何をしてほしいのか説明があまりに不足していて、何故認識されないか説明のしようがなかったのです) 解答ではないのでベストアンサーに選ぶことは残念ながらできませんが、メソッドを使う事で問題は解決しました。本当にありがとうございました。 >>>ozwkさん お陰様で問題は解決いたしましたが、実行コードを以下に提示します。 a = Person("A", 10, "M") b = Person("B", 15, "F") a.set_friend(b) print_friend_info(a) <出力: A 10 Friends with B> print_friend_info(b) <出力: B 15>
guest

回答2

0

ベストアンサー

とりあえず、プログラミングは「こう書けばいい」ってものではありません。簡単に言えば『現実世界のシミュレーション』です。

つまり、『現実世界でならどうするか』を考えてみるといいですよ。

で、今回はコードは書けたが、なぜかうまくいない…という質問ですね。そういう場合はデバッグしましょう。

デバッグ方法の一つとして、「コードを読む」ということをお勧めします。
(出来ればデバッガを使ったりする方が望ましいが…)

コードを読むコツは、『一行レベルで、その行が何をしているかを考えながら読む』です。

今回のclass Perosnとかprint_friend_info関数なんかは単なる定義です。
なので絶対に、それらを呼び出すようなコードがあるはずです。C#とかでいえばMainメソッド、C++で言えばmain関数とかのような場所があるはずです。(Pythonではmain関数等は必須ではないですが)

おそらく、そこで Personクラスをインスタンス化してprint_friend_info関数に渡しているはずです。
その周辺から読みます。

ですが、今回は(この時点ではまだ)提示されていないので、インスタンス化してすぐそのまま渡されていると仮定します。

Python

1# 引数personを受け取り処理するprint_friend_info関数を定義する 2def print_friend_info(person): 3 # 変数 n は personが持っている名前にする(getterで取得) 4 n = person.get_name() 5 # 変数 a は personが持っている年齢にする(getterで取得) 6 a = person.get_age() 7 # 変数 fr は personが持っている友人とする(getterで取得) 8 fr = person.get_friend() 9 # nの値を出力 10 print(n) 11 # aの値を出力 12 print(a) 13 # frが空でないなら 14 if fr: 15 # 変数 fr_is を frの_nameとする 16 fr_is = fr._name 17 # 出力する 18 print(f'Friends with {fr_is}')

で、personが持つ get_nameメソッド等が呼ばれているので、それの中も潜る。

だけど、今回はクラスオブジェクト。なのでデータの状態も考えないといけません。Personのコンストラクタでは、

Python

1class Person(object): 2 # 引数を受け取って設定する 3 def __init__(self, name, age, gender): 4 # 自身の _name は 引数のnameの値とする 5 self._name = name 6 # 自身の _age は 引数のageの値とする 7 self._age = age 8 # 自身の _gender は引数のgenderの値とする 9 self._gender = gender 10 # 自身の _friend は Noneとする 11 self._friend = None

さて、コンストラクタで生成した状態では、それぞれのフィールドの状態はどうなっているでしょうか。

引数にもよりますが、person = Person( "Taro", "21", "M" )のような感じであれば、

_name : Taro _age : 21 _gender : M _friend : None

の状態だと思います。

つまり、nameやらageやらはすでに何らかのデータが入っていると考えられますが、friendは指定されていません。Noneです。つまり未定義。

ヒント: 参考1

この状態で、先ほどのprint_friend_info関数の処理をやってみてください。
つまり『手作業でやってみる』です。料理のレシピなり、数学の手順なりのなんらかの手順と考えてやってみてください。

そうすると、set_friendメソッドを呼ばない限りは、_friend は Noneです。
get_friendで取得しても、Noneなので、if fr:の条件式を満たさないためです。

仮にif fr:を排除したとしても、Noneの状態なので……

……と言う風にデータの状態や処理内容を確認してください。そうすればわかるはずです。
これがデバッグの基本です。
実際にはデバッガなり、いわゆるprintfデバッグなりをしますが、どの方法でも根本的な考えは上記のように、処理とデータの状態を考えるってことです。

投稿2021/11/18 07:59

BeatStar

総合スコア4958

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

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

Qiitahana

2021/11/20 13:39

返信遅くなってしまいすみません。回答ありがとうございます。デバッグのやり方参考にさせていただこうと思います。 デバッグとは違いますが、個別でset_friendを用いてインスタンスにfriendを持たせ、print_friend_infoを呼び出すときちんと友人に関する情報が出力されfriendを持たせていないインスタンスの場合友人の欄には何も出力されない、と正しく動くのですが、それでもprint_friend_info関数自体が認識されないので、根本的にコードに穴があるのかもしれません。しかしそれが自分ではわかりません。 この関数がカバーしきれていないシチュエーションと言いますか、コードの欠陥のようなものはありますか?よろしければご指摘ください。
BeatStar

2021/11/20 23:18

なんかよくわかりません。 そもそも、他の方が仰っているように、『print_friend_info関数自体が認識されない』とはどういう意味でしょうか。 なんか一般的な意味と違う意味で使っている気がします。たとえば『エラーがでる』とかのような。
Qiitahana

2021/11/21 02:22 編集

>『print_friend_info関数自体が認識されない』とはどういう意味でしょうか どうやらプライベートアトリビュートに直接アクセスしては駄目 という事だったようなのです。 (一人でやっているコーディングではなかったのですが、何をしてほしいのか説明があまりに不足していて、何故認識されないか説明のしようがなかったのです) そこで以下コードの様に、frに対してget_name()メソッドを使い、それを変数に格納するようにしたら正常に作動しました。 丁寧に回答してくださったのに申し訳ないですが、こちらで問題解決しました。 いずれにせよ、デバッグの仕方等解説ありがとうございました。 if fr:     fr_name = fr.get_name()     print("Friends with " + fr_name)
guest

0

「上手く認識されません」とはどのような状態でしょうか?
(エラーが発生する、想定外の出力になる など)

以下のように試してみたところ、それらしく動いているように見えます。

python

1 2class Person(object): 3 def __init__(self, name, age, gender): 4 self._name = name 5 self._age = age 6 self._gender = gender 7 self._friend = None 8 9 def __eq__(self, person): 10 return str(self) == str(person) 11 12 def __str__(self): 13 if self._gender == 'M': 14 title = 'Mr' 15 elif self._gender == 'F': 16 title = 'Miss' 17 else: 18 title = 'Ms' 19 20 return title + ' ' + self._name + ' ' + str(self._age) 21 22 def __repr__(self): 23 return 'Person: ' + str(self) 24 25 def get_name(self): 26 return self._name 27 28 def get_age(self): 29 return self._age 30 31 def get_gender(self): 32 return self._gender 33 34 def set_friend(self, friend): 35 self._friend = friend 36 37 def get_friend(self): 38 return self._friend 39 40 41def print_friend_info(person): 42 n = person.get_name() 43 a = person.get_age() 44 fr = person.get_friend() 45 if fr: 46 fr_is = fr._name 47 print(f'Friends with {fr_is}') 48 49 50taro = Person('Taro', 12, 'M') 51hanako = Person('Hanako', 14, 'F') 52 53taro.set_friend(hanako) 54#hanako.set_friend(taro) 55 56print_friend_info(taro) # Friends with Hanako 57print_friend_info(hanako) # hanakoの友達はNoneのままなので何も表示されない

投稿2021/11/18 07:44

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Qiitahana

2021/11/20 13:40

返信遅くなってしまいすみません。回答ありがとうございます。個別でset_friendを用いてインスタンスにfriendを持たせ、print_friend_infoを呼び出すときちんと友人に関する情報が出力されfriendを持たせていないインスタンスの場合友人の欄には何も出力されない、と正しく動くのですが、それでもprint_friend_info関数自体が認識されないので、根本的にコードに穴があるのかもしれません。しかしそれが自分ではわかりません。 この関数がカバーしきれていないシチュエーションと言いますか、コードの欠陥のようなものはありますか?よろしければご指摘ください。
退会済みユーザー

退会済みユーザー

2021/11/20 14:45

やはり「関数自体が認識されない」というのがどのような状況なのか分かりません。print_friend_info関数を定義するよりも前の行でこの関数を使用しようとして"print_friend_info is not defined"みたいなエラーが発生している状態でしょうか?質問文を更新して問題が発生しているコードを貼ってもらったほうが解決が早いと思います。
Qiitahana

2021/11/21 02:24

>「関数自体が認識されない」というのがどのような状況なのか分かりません どうやらプライベートアトリビュートに直接アクセスしては駄目 という事だったようなのです。 (一人でやっているコーディングではなかったのですが、何をしてほしいのか説明があまりに不足していて、何故認識されないか説明のしようがなかったのです) そこで以下コードの様に、frに対してget_name()メソッドを使い、それを変数に格納するようにしたら正常に作動しました。 丁寧に回答してくださったのに申し訳ないですが、こちらで問題解決しました。 ありがとうございました。 if fr:     fr_name = fr.get_name()     print("Friends with " + fr_name)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問