Nie mogę zrozumieć, dlaczego zmienna w klasie nie jest aktualizowana.

class Pile:
    def __init__(self, cards):
        self.cards = cards

    def __str__(self):
        result = ' '.join(self.cards)
        return result

    def __repr__(self):
        return f'Pile({self.cards})'

    def flip(self):
        self.cards.reverse()
        return eval(f'Pile({self.cards})')

To jest część mojego kodu. Kiedy uruchomię poniższy kod,

cards = Pile(['AH', '3S', 'KC'])
print(cards)
# AH 3S KC
cards
# Pile(['AH', '3S', 'KC'])
cards.flip().flip()
# Pile(['AH', '3S', 'KC'])
print(cards)

Spodziewałem się „AH 3S KC”, ale dostałem „KC 3S AH”. „KC 3S AH” jest wynikiem działania cards.flip () .

Myślę, że cards.flip (). Flip () ta część nie działa, ponieważ kiedy napisałem cards.flip () i ponownie cards.flip () , to działa dokładnie tak, jak chciałem. Nie wiem, na czym polega problem. Czy mógłbyś to wyjaśnić? Dziękuję za przeczytanie.

1
jiwon koh 1 kwiecień 2020, 12:18

3 odpowiedzi

Najlepsza odpowiedź

Pozbądź się funkcji eval w swojej metodzie flip(). Odwróć wystąpienie Pile w metodzie flip, a następnie zwróć je.

Kod


class Pile:
    def __init__(self, cards):
        self.cards = cards

    def __str__(self):
        result = ' '.join(self.cards)
        return result

    def __repr__(self):
        return f'Pile({self.cards})'

    def flip(self):
        self.cards.reverse()
        return self

cards = Pile(['AH', '3S', 'KC'])
print(cards)
# AH 3S KC
cards
# Pile(['AH', '3S', 'KC'])
cards.flip().flip()

# Pile(['AH', '3S', 'KC'])
print(cards)

Wyjście

enter image description here

2
Saimon 1 kwiecień 2020, 11:01

Twoja metoda flip musi działać na instancji Pile . Dlatego flip musi zwrócić instancję.

class Pile:
    def __init__(self, cards):
        self.cards = cards

    def __str__(self):
        result = ' '.join(self.cards)
        return result

    def __repr__(self):
        return f'Pile({self.cards})'

    def flip(self):
        self.cards.reverse()
        return self

Kiedy uruchamiam przykładowy kod, otrzymuję listę początkową, której oczekiwałbym po podwójnym przewróceniu:

cards = Pile(['AH', '3S', 'KC'])
print(cards)
# AH 3S KC
cards
# Pile(['AH', '3S', 'KC'])
cards.flip().flip()
# Pile(['AH', '3S', 'KC'])
print(cards)

Wynik:

AH 3S KC
AH 3S KC
1
ma3oun 1 kwiecień 2020, 09:34

Nie odwracasz tego samego obiektu dwa razy, ale zwracasz niezależne kopie pierwszego obiektu:

Masz instancję Pile o nazwie cards. Wołasz na to flip(). Odwraca wewnętrzny stos kart cards i zwraca eval(f'Pile({self.cards})').

eval tworzy NOWY obiekt z Twoim obecnym self.cards jako parametrami początkowymi - które następnie odwracasz (jeszcze inny obiekt, który tworzy kolejny na eval ), a następnie wyrzucasz wszystkie utworzone obiekty, ponieważ nigdy ich nigdzie nie przechowujesz.

Następnie drukujesz (po odwróceniu) oryginalną instancję cards.

cards = Pile(['AH', '3S', 'KC'])

print(cards, id(cards))

cards2 = cards.flip() # you flip this another time w/o storing it anywhere

print(cards2, id(cards2))  # print with obj id to see its different
print(cards, id(cards))    # print with obj id to see its different

Wynik:

AH 3S KC 140645422863584 # cards
KC 3S AH 140645422863976 # result of cards.flip() as new object 
KC 3S AH 140645422863584 # your original cards once flipped

Chcesz:

def flip(self):
    self.cards.reverse()
    return self  # return yourself for chaining

Przeczytaj o eval w dokumencie.

1
Patrick Artner 1 kwiecień 2020, 09:46