ここでいくつかのこと:
リストにアイテムを表示しようとすると、プログラムは次のように表示します。
ユーザー クラスのデフォルトの表示は、 のようなもの<team.Team object at 0x000000000332A978>
です。何か違うものを表示したい場合は、何を表示したいかを Python に伝える必要があります。これには、 と の 2 つの別個の関数があり__repr__
ます__str__
。1 つ目はプログラマーの表現であり、2 つ目はユーザーの表現です。2 つの異なる表現が必要ない場合は、定義するだけで、__repr__
必要なときにいつでもそれを使用できます__str__
。
したがって、これを修正する非常に簡単な方法は、これをTeam
クラスに追加することです。
def __repr__(self):
return 'Team("{}")'.format(self._name)
を呼び出すとleague.addTeam('Dodgers')
、代わりにprint(l._table)
が得られます。[Team("Dodgers")]
[<team.Team object at 0x000000000332A978>]
一方、これらの 2 つの方法は、おそらくあなたが望むものではありません。
def removeTeam(self,team):
self._table.remove(team)
def returnPosition(self,team):
return self._table.index(team)
これらは、オブジェクトを指定してチームを削除または検索しTeam
ます。名前や、名前から新しくTeam
作成されたものではなく、 に保存されているまったく同じオブジェクトへの参照_table
です。これはあまり便利ではなく、名前だけで呼びたいようです。
これを修正するには 2 つの方法があります。Team
このメソッドをクラスに追加することで、オブジェクト ID ではなく名前で比較するように変更できます。
def __eq__(self, other):
return self._name == other._name
これが意味することは、 と言うとTeam('Giants') == Team('Giants')
、False ではなく true になるということです。最初のチームが別のリーグに属し、別の WL 記録を持っていたとしても (たとえば、サンフランシスコの野球の「ジャイアンツ」とニューヨークのサッカーの「ジャイアンツ」のように)、Python が彼らは今、同じチームです。もちろん、それが望ましくない場合は、__eq__
より適切と思われる他の関数を作成できます。
とにかく、これを行うと、index
および関数は、まったく同じチームではなく、同じ名前のチームremove
を見つけることができるようになります。Team
def removeTeam(self,team_name):
self._table.remove(Team(team_name))
def returnPosition(self,team_name):
return self._table.index(Team(team_name))
この方法を使用する場合は、すべての比較方法を定義することを検討することをお勧めします。これにより、たとえば、チームのリストを並べ替え、名前で並べ替えることができます。
または、これらのメソッドを変更して、平等に基づいて機能しないようにすることもできます。たとえば、次のように再定義します。
def removeTeam(self,team_name):
self._table = [team for team in self._table if team._name != team_name]
def returnPosition(self,team_name):
return [team._name for team in self._table].index(team_name)
これらがどのように機能するかを理解するために、リスト内包表記を読むことに慣れていない場合は、それぞれを同等のループに戻します。
self._table = [team for team in self._table if team._name != team_name]
temp = []
for team in self._table:
if team._name != team_name:
temp.append(team)
self._table = temp
これをステップ実行するtemp
と、削除したいチームを除いて、テーブル内のすべてのチームのリストが表示され、古いものself._table
を新しいフィルター処理されたものに置き換えます。(同じ考えを書く別の方法はfilter
、関数を知っていれば、 を使用することです。)
通常は、リストをその場で変更するよりも、フィルター処理された新しいリストを作成する方が適切です。これを行わないパフォーマンス上の理由がある場合もあれば、非常に複雑で理解しにくいものになる場合もありますが、通常は、理由を説明する方が速くて簡単です。また、リストを変更すると、次のような問題が発生します。
for i, value in enumerate(mylist):
if value == value_to_remove:
del mylist[i]
これでしばらく遊んでみると、実際には機能しないことがわかります。理由を理解するのは少し複雑で、後になるまで学習したくないでしょう。この問題を解決するための通常のトリックは、リストのコピーを反復処理することです…しかし、一度それを行うと、最悪のフィルタリングと最悪の場所での削除が同時に発生します。
2 番目の関数は少し巧妙すぎるかもしれませんが、見てみましょう。
def returnPosition(self,team_name):
return [team._name for team in self._table].index(team_name)
最初に、元のリストと同じようなリストを作成していますが、これはチーム オブジェクトではなく名前だけのリストです。繰り返しますが、リスト内包表記を分解しましょう:
temp = []
for team in self._table:
temp.append(team._name)
または、英語に翻訳してみてください: これは、テーブル内のすべてのチームのチーム名のリストです。
これはチーム名のリストなので、これを使用index(team_name)
して検索します。そして、2 つのリストは同じ形をしているので、元のリストでもこれが正しいインデックスであることがわかりteam
ます。
より簡単な解決策は、 の から への名前のマッピング に変更_tables
することです。これはおそらく最も Pythonic なソリューションです。リスト内包表記を記述して単純な操作を行うよりもはるかに簡単に見えます。(これはおそらく最も効率的でもありますが、本当に巨大なリーグがない限り、ほとんど意味がありません。) そして、何も必要ありません。それを行うには:list
Team
dict
Team
returnPosition
def __init__(self):
self._table={}
def addTeam(self,name):
self._table[name]=Team(name)
def removeTeam(self,team_name):
del self._table[team_name]
def returnPosition(self,team_name):
return team_name
def updateLeague(self,team1_name1,team_name2,score1,score2):
if score1>score2:
self._table[team_name1].win()
self._table[team_name2].loss()
elif score1==score2:
self._table[team_name1].draw()
self._table[team_name2].draw()
elif score1<score2:
self._table[team_name1].loss()
self._table[team_name2].win()
returnPosition
チーム名自体をポジションとして返すように定義したことに注意してください。考えてみると、dict
キーはインデックスとまったく同じように使用されるlist
ため、必要な「古い」API 用に誰かが書いたコードはreturnPosition
、「新しい」API でも機能します。(おそらく、私たちが を使用する必要がある問題を割り当てた教師にこれを売り込もうとはしませんreturnPosition
が、1.3 のユーザーが 2.0 に簡単に移行できるようにしたいと考えていた実際のライブラリの場合は、おそらくそうするでしょう。 )
これには、他にいくつかの変更が必要です。displayList
andでは、 ;ではなくsaveList
反復します。で、 に変更します。といえば、これらのローカル変数の名前を 、 、 から 、 、 、 に変更することを検討することをお勧めします。self._table.values()
self._table
loadList
self._table.append(team)
self._table[a] = team
loadList
a
b
c
d
name
wins
losses
draws
その他のコメント:
- kreativitea がコメントで述べているように、「プライベート」変数を作成してから、何もしないアクセサー メソッドを Python に追加するべきではありません。これは、実際のコードを隠すボイラープレートに過ぎず、1 日何時間もかけてデバッグすることになるばかげたタイプミスで間違いを犯す可能性があるもう 1 つのことです。
name
、wins
、losses
などの名前のメンバーを用意して、それらに直接アクセスするだけです。(インターフェイスを変更せずに将来実装を置き換えることができないため、これは悪いスタイルだと誰かが言った場合、それは Java と C++ でのみ当てはまり、Python では当てはまりません。実装を置き換える必要がある場合は、を読んでください@property
。)
- その必要はありません。
print("""""")
また、誤って文字数を数え間違える可能性が非常に高くなり"
ます。(特に、一部の IDE はこれによって実際に混乱し、複数行の文字列が決して終わらないものと考えるためです。) ただprint()
.
while
loop( while x!="q":
) と internalの両方で同じ終了条件を持っていますbreak
。両方の場所でそれは必要ありません。に変更するかwhile True:
、または削除します ( dobreak
を作成するだけなので、ループ内で特別なケースにする必要はまったくありません)。options("q")
print("Goodbye")
- ステートメントのチェーンが長い場合は、それを短い関数
elif
に変換できるかどうかを考えてください。dict
この場合、それが良いアイデアかどうかはわかりませんが、常に考えて明確な決定を下す価値があります。
最後のアイデアは次のようになります。
def addTeam():
name=input("Enter the name of the team:")
l.addTeam(name)
def removeTeam():
teamToRemove=input("Enter the name of the team you want to remove:")
l.removeTeam(teamToRemove)
def recordGame():
team1=input("What is the name of the team?")
ans1=int(input("Enter the number of goals for the first team:"))
team2=input("What is the name of the team?")
ans2=int(input("Enter the number of goals for the second time:"))
l.updateLeague(team1,team2,ans1,ans2)
optionsdict = {
"a": addTeam,
"d": l.displayList,
"s": l.saveList,
"l": l.loadList,
"r": removeTeam,
"rec": recordGame,
}
def options(x):
func = optionsdict.get(x)
if func:
func()
私が言ったように、このケースで実際に明確になるかどうかはわかりませんが、検討する価値はあります。