45463


参考書内で”戦争”と呼ばれるゲームのコードを作っていた際の質問です。  
該当ページ、辞書として用いている参考書、ネットの情報を参照しても不明点が解決せず、これ以上考えるのはあまりよくないと思い質問させていただきます。  
初歩的な質問だとは思いますが、これを機にクラスへの理解を深めたいです。

コードが長いため、下に掲載します。

①Cardクラスのスイート、２・３番目のメソッド  
`__lt__`,`__gt__`の引数である`c2`がどこでこのメソッドに渡されているのかわかりません。  
なので、ここのif文にあるc2.valueがどこから引っ張ってこられているのか全く分かりません。

②,③（おそらく同類の質問）  
Gameクラスのスイート、４番目のメソッド  
whileループの中２番目のif文の`self.p1.wins`の参照の仕方について  
☆☆☆を参照する際にwinsにselfをつけなくてもいいのですか？

同クラス、５番目のメソッド  
ここでの２つのif文returnに渡す変数はselfをつけてもつけなくてもよいのですか？  
書いているようにselfつけてもつけなくても正常に動きはしました。

参考書では、参照する際にはselfをつけるように記載されていたので少々混乱しています。

コードです。

[code]

    class Card:
        suits=["spades","hearts","diamonds","clubs"]
    
        values=[None,None,
                "2","3","4","5","6","7","8","9",
                "10","Jack","Queen","King","Ace"]
    
    
        def __init__(self,v,s):
            """スート・マークはともにint型オブジェクトで扱います"""
            self.value=v
            self.suit=s
    
        def __lt__(self,c2): #__lt__は比較用の特殊メソッドです（より小さい）
            #c2がどこで作られるオブジェクトなのかわかってません。
            #でも、__lt__ or __gt__メソッドが呼ばれればその時の引数に渡せばいい。え、でもそれもどこ？ｗｗ
            if self.value<c2.value:
                return True
            if self.value==c2.value:
                if self.suit<c2.suit:
                    return True
                else:
                    return False
    
            return False
    
        def __gt__(self,c2): #__gt__は比較用の特殊メソッドです（より大きい）
            if self.value>c2.value:
                return True
            if self.value==c2.suit:
                return True
                if self.suit>c2.suit:
                        return True
                else:
                        return False
    
        def __repr__(self):
            v=self.values[self.value]+" of "+self.suits[self.suit]
            return v
    
    from random import shuffle #意味をきちんと言えるようにしましょう。
    
    class Deck:
        def __init__(self):
            self.cards=[]
            for i in range(2,15): #トランプの５２枚のカードを用意しています。
                for j in range(4):
                    self.cards.append(Card(i,j))
            shuffle(self.cards)
    
        def rm_card(self):
            if len(self.cards)==0: #カードの枚数が０になると終わりです。
                return
            return self.cards.pop() #引くカードの被りを避けています。
    
    """
    deck=Deck()
    for card in deck.cards: #参照の仕方をきちんと覚えましょう。
        print(card)
    
    このコードによりトランプが正確に出力されるか確認しました。
    また、ここまでのエラーに直結する要素は全て解決されています。
    """
    
    class Player: #後で使うための下準備です。
        def __init__(self,name):
            self.wins=0 #☆☆☆
            self.card=None
            self.name=name
    
    class Game: #これ、”ここ”でDeck呼び出してるけど、継承した時との違いは？
        def __init__(self):
            name1=input("プレイヤー１の名前 ")
            name2=input("プレイヤー２の名前 ")
            self.deck=Deck() #ここ
            #上はDeckクラスのオブジェクトとしてカードをdeckのセルフ変数に参照しています。
            self.p1=Player(name1)
            self.p2=Player(name2)
    
        def wins(self,winner):
            w="このラウンドは{}が勝ちました"
            w=w.format(winner) #winsメソッドの引数winnerが上の{}に追加されます。
            print(w)
    
        def draw(self,p1n,p1c,p2n,p2c): #それぞれのプレイヤーが引いたカードをコールします。
            d="{}は{}、{}は{}を引きました。"
            d=d.format(p1n,p1c,p2n,p2c)
            print(d)
    
        def play_game(self):
            cards=self.deck.cards #Deckクラスのself.deckオブジェクトを引数としてDeckクラス内のcardsメソッドに渡します。
            print("Let's begin the game called war!")
            while len(cards)>=2:
                m="qで終了、それ以外のキーでPlay:"
                response=input(m)
                if response=="q":
                    break
                p1c=self.deck.rm_card()
                p2c=self.deck.rm_card()
                p1n=self.p1.name
                p2n=self.p2.name
                self.draw(p1n,p1c,p2n,p2c)
                if p1c>p2c:
                    self.p1.wins+=1 #これ、☆☆☆を参照しているのだろうけどwinsにselfはいらない？
                    self.wins(self.p1.name)
                else:
                    self.p2.wins+=1
                    self.wins(self.p2.name)
    
            win=self.winner(self.p1,self.p2)
            print("ゲーム終了、{}の勝利です！".format(win))
        def winner(self,p1,p2):
            if p1.wins>p2.wins:
                return self.p1.name #元はp1.nameだったけど、self変数にしなくていいのか迷ったのでいったんself変数で書いてます。
            if p1.wins<p2.wins:
                return p2.name
            return "引き分け" #elseの処理これでもできるんだっけ、覚えてないです。
    
    
    game=Game()
    game.play_game()
    
[/code]

P.S.  
＃は自分がコードを書いている際に思ったことなどを書いています。  
質問したところ以外にも疑問点を書いていますが、自分でまだ十分にしらべられてないので  
もし、調べてわからなければもう一度追加質問させていただきます。  
また、どこが原因なのかわからないため、全体を掲載します。ご容赦ください。  
質問該当箇所はわかりやすく記したつもりではありますが、わかりにくい点があればご指摘ください。


CC BY-SA 4.0
2018-07-09T15:15:26.660
45461
2018-07-09T15:48:29.153
2018-07-09T15:28:58.927
19110
29238
question
python
クラスの引数・変数・変数の参照についての質問です。


### ① `__lt__(self, c2)` の `c2` とは何か？

`<` で比較するときの右側の引数です。こちらの別質問をご覧ください: [「クラスの関数で、self
以外の変数が何なのか分からない」](https://ja.stackoverflow.com/q/44262/19110)

### ② `self.p1.wins += 1` の `wins` に `self` はつけなくて良い？

つけません。

`self` は自分自身のことを示す特別なオブジェクトなのでした。また、`self.p1` もオブジェクトであり、`Game` クラスのインスタンス変数
`p1` のことを指しています。

つまりこの行では「`Game` クラスのインスタンス変数 `p1`」のインスタンス変数 `wins` を操作しようとしているのです。`self.p1`
の時点でどのオブジェクトの `wins` を操作しようとしているのか明らかです。

また、`self` という名前は同じですが、`Game` クラスのメソッドの中で使われる `self` は `Game`
クラスのオブジェクトそのものを指しており、`Player` クラスのオブジェクトを指しているわけではないことにも注意してください。

### ③ 関数 `winner(self, p1, p2)` において `self.p1` と `p1` に差はある？

少なくとも `self.p1` と `p1` に差はあります。

`self.p1` は自分自身がインスタンス変数として持っている `p1` を指す一方、`p1` は関数 `winner` の引数として与えられた `p1`
を指します。

「`self` をつけてもつけなくても同じように動作した」とのことですが、これは `play_game()` 関数の中で `winner`
関数を呼び出す際に以下のようにしているからです。

[code]

    win = self.winner(self.p1, self.p2)
    
[/code]

上のように使う限りは、`p1` と `self.p1` が一致するため、`self` があってもなくても同じ動作になります。(蛇足:
このような使い方しかしないのであれば、`winner` 関数の引数 `p1`, `p2`
は不要だと思われます。書籍中の別の箇所で違う使い方をするのかもしれません。)


CC BY-SA 4.0
2018-07-09T15:48:29.153
45463
2018-07-09T15:48:29.153
19110
45461
answer