python オブジェクトについて
python でオブジェクトを作る?練習をしています。
野球チームの勝敗と勝率を計算してこのように表示させたいのですが
野球チームをクラスにして、
チーム名、勝数、負数、引き分けと勝率を
それぞれ表示させたいのですが、
スペースを開けて表示させたいのですができないのです。
ljust()を多用すると、このようなエラーになってしまい、思うようにいきません。
どなたか良い解決策?ご存じないですか、よろしくお願いいたします。
python でオブジェクトを作る?練習をしています。
野球チームの勝敗と勝率を計算してこのように表示させたいのですが
野球チームをクラスにして、
チーム名、勝数、負数、引き分けと勝率を
それぞれ表示させたいのですが、
スペースを開けて表示させたいのですができないのです。
ljust()を多用すると、このようなエラーになってしまい、思うようにいきません。
どなたか良い解決策?ご存じないですか、よろしくお願いいたします。
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の質問や記事ではソースコードを画像ではなく文字で貼り付けることができます.書式は
(空行)
```言語名:タイトル
コード本文
```
です.コピペ等で解答しやすくなる上に再現性も担保できますので,次回投稿からはご検討ください.
@Misaku
Questioner
ちなみに、せっかくf文字列を使っていらっしゃるなら、書式指定が利用可能です。
f"{式:>幅}"
f"{式:<幅}"
なお、数値型はデフォルトで右寄せ、文字列は左寄せです。
なので、質問文の画像と同じ出力を得るだけなら次のようになります。
(@PondVillege 様のコードを起点にしてください。)
f"{self.name:8}{self.win:3} {self.lose:4} {self.draw:4} {self.win_rate:.3}"
いずれにしても、変数の型は意識してコーディングした方がいいですね。
クラス定義の練習でしたらなおさらです。
@Misaku
Questioner