1

プロジェクトのリーグテーブルを作成する必要があります。3 つのファイルが必要で、2 つのファイルは 1 つのクラスで構成され、最後のファイルはプログラムを実行するためのものです。すべての部分を完了しましたが、チームを追加するメソッドを呼び出すと、プログラムは名前を追加しますが、チームのリストに挿入しません(そうするべきです)。リスト内のアイテムを表示しようとすると、プログラムは実際のチームを表示する代わりにエラー メッセージを表示します。

どうすれば修正できますか?助けていただければ幸いです。:)

4

1 に答える 1

1

ここでいくつかのこと:

リストにアイテムを表示しようとすると、プログラムは次のように表示します。

ユーザー クラスのデフォルトの表示は、 のようなもの<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 なソリューションです。リスト内包表記を記述して単純な操作を行うよりもはるかに簡単に見えます。(これはおそらく最も効率的でもありますが、本当に巨大なリーグがない限り、ほとんど意味がありません。) そして、何も必要ありません。それを行うには:listTeamdictTeamreturnPosition

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 に簡単に移行できるようにしたいと考えていた実際のライブラリの場合は、おそらくそうするでしょう。 )

これには、他にいくつかの変更が必要です。displayListandでは、 ;ではなくsaveList反復します。で、 に変更します。といえば、これらのローカル変数の名前を 、 、 から 、 、 、 に変更することを検討することをお勧めします。self._table.values()self._tableloadListself._table.append(team)self._table[a] = teamloadListabcdnamewinslossesdraws

その他のコメント:

  • kreativitea がコメントで述べているように、「プライベート」変数を作成してから、何もしないアクセサー メソッドを Python に追加するべきではありません。これは、実際のコードを隠すボイラープレートに過ぎず、1 日何時間もかけてデバッグすることになるばかげたタイプミスで間違いを犯す可能性があるもう 1 つのことです。namewinslossesなどの名前のメンバーを用意して、それらに直接アクセスするだけです。(インターフェイスを変更せずに将来実装を置き換えることができないため、これは悪いスタイルだと誰かが言った場合、それは Java と C++ でのみ当てはまり、Python では当てはまりません。実装を置き換える必要がある場合は、を読んでください@property。)
  • その必要はありません。print("""""")また、誤って文字数を数え間違える可能性が非常に高くなり"ます。(特に、一部の IDE はこれによって実際に混乱し、複数行の文字列が決して終わらないものと考えるためです。) ただprint().
  • whileloop( 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()

私が言ったように、このケースで実際に明確になるかどうかはわかりませんが、検討する価値はあります。

于 2012-12-06T19:28:09.767 に答える