Misaku
@Misaku (Misaku suzuki)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

python オブジェクトについて

python でオブジェクトを作る?練習をしています。

野球チームの勝敗と勝率を計算してこのように表示させたいのですが
スクリーンショット 2022-03-02 0.46.09.png

野球チームをクラスにして、
チーム名、勝数、負数、引き分けと勝率を
それぞれ表示させたいのですが、
スペースを開けて表示させたいのですができないのです。
スクリーンショット 2022-03-02 0.42.30.png

ljust()を多用すると、このようなエラーになってしまい、思うようにいきません。
スクリーンショット 2022-03-02 0.51.39.png

どなたか良い解決策?ご存じないですか、よろしくお願いいたします。

0

2Answer

ljust()を多用すると、このようなエラーになってしまい、思うようにいきません。

プログラムというものは,「思うように」動くのではなく「書いた通り」に動きます.
エラーが出たのであれば,エラーが出ないように論理的思考のもと修正すべきです.

今回のエラー文

AttributeError: 'int' object has no attribute 'ljust'

そのまま翻訳機にかけると

AttributeError: 'int' オブジェクトには 'ljust' という属性がありません。

ということになります.ここで,self.name'str'オブジェクトだったので1つ目のプログラムでは動きましたが,ljustを多用した瞬間,すなわちself.winにも適用した途端動かなくなったというのは,self.win'int'オブジェクトだからです.
Baseball_Team()の初期化の際の第2引数は77という整数値であり,これにはljustというメソッド/属性は存在しません.

解決のためには,ljustメソッドを持つstrオブジェクトに変換してあげる必要があります.したがって,表示するときにstr()で変換する方法

def show_team_result(self):
    show_team_result = (f"{self.name.ljust(8)}{str(self.win).ljust(8)}")\

か,そもそもBaseball_Teamに値を渡すときに'str'オブジェクトに変換して渡してあげる

Giants = Baseball_Team("Giants", "77", "64", "2")

かのどちらかになります.

前者の方は,デフォルト引数が'str'オブジェクトで設定されているのに'int'オブジェクトを渡していることになりとても不自然です.文字列で扱うか整数で扱うかどちらかにしたほうが良さそうです.勝率の計算を含むのであれば整数で扱うようにしたほうが一貫性があります.

また,Pythonならではの機能として特殊メソッドが便利なので,オブジェクトの情報を表示されるときはそちらを使われると面白くなります.

class Baseball_Team:
    def __init__(self, name, win, lose, draw):
        self.name = name
        self.win = win
        self.lose = lose
        self.draw = draw
        self.win_rate = 0
    
    def calc_win_rate(self):
        self.win_rate = self.win / (self.win + self.lose)
        
    def __str__(self):
        return f"{self.name.ljust(8)}{str(self.win).ljust(8)}{str(self.lose).ljust(8)}{str(self.draw).ljust(8)}{str(round(self.win_rate, 3)).ljust(8)}"
    
    def __eq__(self, other):
        return self.win_rate == other.win_rate
        
    def __lt__(self, other):
        return self.win_rate < other.win_rate

# 全チーム(アルファベット順)
bts = [
    Baseball_Team("BayStars", 71, 69, 3),
    Baseball_Team("Carp", 70, 70, 3),
    Baseball_Team("Dragons", 68, 73, 2),
    Baseball_Team("Giants", 77, 64, 2),
    Baseball_Team("Swallows", 59, 82, 2),
    Baseball_Team("Tigers", 69, 68, 6)
]

# 1つだけ表示
print(Baseball_Team("Giants", 77, 64, 2), end="\n\n")

# 全部表示
print("".join(map(lambda x: x.ljust(8), ["team", "win", "lose", "draw", "rate"])))
print("\n".join(map(str, bts)), end="\n\n")

# 勝率を計算
for team in bts:
    team.calc_win_rate()
    
# 勝率順に並べ替え
bts.sort(reverse = True)

# 全部表示
print("".join(map(lambda x: x.ljust(8), ["team", "win", "lose", "draw", "rate"])))
print("\n".join(map(str, bts)))
出力結果
Giants  77      64      2       0       

team    win     lose    draw    rate    
BayStars71      69      3       0       
Carp    70      70      3       0       
Dragons 68      73      2       0       
Giants  77      64      2       0       
Swallows59      82      2       0       
Tigers  69      68      6       0       

team    win     lose    draw    rate    
Giants  77      64      2       0.546   
BayStars71      69      3       0.507   
Tigers  69      68      6       0.504   
Carp    70      70      3       0.5     
Dragons 68      73      2       0.482   
Swallows59      82      2       0.418 

print(Baseball_Team("Giants", 77, 64, 2))をできるようにするために__str__メソッドを定義し,ソートを扱えるようにするために__lt____eq__を定義しました.他にも特殊メソッドはたくさんありますが,ひとまずこれだけ実装してみました.

終わりに

今書いたように,Qiitaの質問や記事ではソースコードを画像ではなく文字で貼り付けることができます.書式は

(空行)
```言語名:タイトル
コード本文
```

です.コピペ等で解答しやすくなる上に再現性も担保できますので,次回投稿からはご検討ください.

3Like

Comments

  1. @Misaku

    Questioner

    ありがとうございます! ソースコード了解です、ありがとう

    かなり参考になりそうです。助かります!

ちなみに、せっかくf文字列を使っていらっしゃるなら、書式指定が利用可能です。

  • 右寄せ: f"{式:>幅}"
  • 左寄せ: f"{式:<幅}"

なお、数値型はデフォルトで右寄せ、文字列は左寄せです。
なので、質問文の画像と同じ出力を得るだけなら次のようになります。
(@PondVillege 様のコードを起点にしてください。)

f"{self.name:8}{self.win:3} {self.lose:4} {self.draw:4} {self.win_rate:.3}"

いずれにしても、変数の型は意識してコーディングした方がいいですね。
クラス定義の練習でしたらなおさらです。

3Like

Comments

  1. @Misaku

    Questioner

    ありがとうございます。これは使いやすいですね!
    もっと練習します。

Your answer might help someone💌