• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Problem z funkcją clear()

Aruba Cloud - Virtual Private Server VPS
0 głosów
509 wizyt
pytanie zadane 16 września 2022 w Python przez kacper1445 Mądrala (5,050 p.)
edycja 16 września 2022 przez kacper1445

Hej, napisałem metodę, która ma automatycznie tworzyć karty do gry:

    def _make_deck() -> list:
        figures = ['A', 'K', 'Q', 'J', '10', '9', '8', '7', '6', '5', '4', '3', '2']
        colors = ['wino', 'serce', 'trefl', 'wino']
        deck = []
        card = []

        for col in colors:
            for fig in figures:
                card.clear()
                card.append(fig)
                card.append(col)
                print(card)
                deck.append(card)
                print(deck, '\n')
        return deck

Problem leży w tym, że przy takim zapisie, karty dodają się w bardzo dziwny sposób:

['A', 'pik'] -> pojedyńcza karta
[['A', 'pik']] -> aktualny deck po dodaniu karty

['K', 'pik']
[['K', 'pik'], ['K', 'pik']] 

['Q', 'pik']
[['Q', 'pik'], ['Q', 'pik'], ['Q', 'pik']] 

To samo się dzieje w momencie użycia zapisu del card[:]

    def _make_deck() -> list:
        figures = ['A', 'K', 'Q', 'J', '10', '9', '8', '7', '6', '5', '4', '3', '2']
        colors = ['wino', 'serce', 'trefl', 'wino']
        deck = []
        card = []

        for col in colors:
            for fig in figures:
                del card[:]
                card.append(fig)
                card.append(col)
                print(card)
                deck.append(card)
                print(deck, '\n')
        return deck

Oraz to samo kiedy zapiszę card *= 0.

    def _make_deck() -> list:
        figures = ['A', 'K', 'Q', 'J', '10', '9', '8', '7', '6', '5', '4', '3', '2']
        colors = ['pik', 'karo', 'trefl', 'wino']
        deck = []
        card = []

        for col in colors:
            for fig in figures:
                card *= 0
                card.append(fig)
                card.append(col)
                print(card)
                deck.append(card)
                print(deck, '\n')
        return deck

 

Natomiast jeżeli zmienię tylko jedną rzecz w kodzie, mianowicie zamiast card.clear(), del card[:] lub card *= 0, napiszę card = [], wszystko działa poprawnie.

    def _make_deck() -> list:
        figures = ['A', 'K', 'Q', 'J', '10', '9', '8', '7', '6', '5', '4', '3', '2']
        colors =['wino', 'serce', 'trefl', 'wino']
        deck = []
        card = []

        for col in colors:
            for fig in figures:
                card = []
                card.append(fig)
                card.append(col)
                print(card)
                deck.append(card)
                print(deck, '\n')
        return deck

['A', 'pik'] -> pojedyńcza karta
[['A', 'pik']] -> aktualny deck

['K', 'pik']
[['A', 'pik'], ['K', 'pik']] 

['Q', 'pik']
[['A', 'pik'], ['K', 'pik'], ['Q', 'pik']] 

 

Ktoś jest w stanie mi wytłumaczyć skąd się to bierze? 

2 odpowiedzi

+2 głosów
odpowiedź 16 września 2022 przez Whistleroosh Maniak (57,400 p.)
wybrane 16 września 2022 przez kacper1445
 
Najlepsza
for elem in deck:
    print(id(elem))

print(id(card))

Jeżeli uruchomisz powyższy kod to zobaczysz, że wszystkie elementy listy deck wskazują na ten sam obiekt, którym jest lista card Więc jakakolwiek zmiana listy card będzie odzwierciedlona na wszystkich elementach listy deck

W przypadku gdy robiłeś card=[] za każdym razem tworzyłeś nową listę, czyli każdy element w deck był innym obiektem.

komentarz 16 września 2022 przez kacper1445 Mądrala (5,050 p.)

Hmm ciekawe. A co np z takim kodem:

a = 2
c = []
c.append(a)
print(id(a))
a += 1
c.append(a)
print(c)
print(id(c[0]), id(c[1]))

Kod działa poprawnie, a jednak nie tworzę żadnej nowej zmiennej tylko zmieniam w niej wartość. Tak samo właśnie jak w przykładzie z kartami. Czegoś tutaj nie rozumiem.

komentarz 16 września 2022 przez Whistleroosh Maniak (57,400 p.)

Wbrew pozorom gdy zrobiłeś a += 1, stworzyłeś nowy obiekt 3 i zmienna a teraz wskazuje na to 3. To się dzieje dlatego, że wartości numeryczne są w pythonie immutable. Poczytaj sobie o immutable vs mutable. Na listach działało to inaczej bo one są mutable.

komentarz 16 września 2022 przez kacper1445 Mądrala (5,050 p.)
Okej, poczytam o tym. Dzięki wielkie!
komentarz 16 września 2022 przez VBService Ekspert (256,600 p.)
edycja 16 września 2022 przez VBService
a = 2
c = []
c.append(a)
print(id(a))
a += 1
c.append(a)
print(c)
print(id(c[0]), id(c[1]))

 do a = 2 dodałeś 1 (a += 1  a = a + 1) czyli a ma teraz wartość 3, i a nie jest list-ą tylko zmienną typu integer, dodana do list-y c (z nową przypisaną wartością) jest traktowana jako nowa wartość
c[0] inne id od id c[1]

[ on-line ]

a = 2
c = []
c.append(a)
print(id(a))

a += 1

c.append(a)
print(c)
print(id(a), id(c[0]), id(c[1]))

 

wink sprawdź to

[ on-line ]

a = 2
c = []
c.append(a)
print(id(a))

a = 2

c.append(a)
print(c)
print(id(a), id(c[0]), id(c[1]))

[ on-line ]

a = 2
c = []
c.append(a)
print(id(a))

a = 1

c.append(a)
print(c)
print(id(a), id(c[0]), id(c[1]))

[ on-line ]

a = 2
c = []
a += 1
c.append(a)
print(id(a))

a = 3

c.append(a)
print(c)
print(id(a), id(c[0]), id(c[1]))

[ on-line ]

c = []

a = 2
c.append(a)
print(id(a))

a = 3
c.append(a)
print(id(a))

a = 2
c.append(a)
print(id(a))

a = 3
c.append(a)
print(id(a))

print(id(c[0]), id(c[1]), id(c[2]), id(c[3]), c)

 

0 głosów
odpowiedź 16 września 2022 przez VBService Ekspert (256,600 p.)
edycja 18 września 2022 przez VBService

Twoja card to jest lista, a deck też jest listą, która zawiera listy card, ponieważ list-a w python-ie dopuszcza duplikaty więc używając kodu 

[ on-line ]

a = []
b = []

a.append(1)
a.append(1)
b.append(a)
print('1.', b)

a.clear()
a.append(2)
a.append(2)
b.append(a)
print('2.', b)

del a[:]
a.append(3)
a.append(3)
b.append(a)
print('3.', b)

a *= 0
a.append(4)
a.append(4)
b.append(a)
print('4.', b)

print()
for a in b:
    print(id(a), a) # 4 kopie tej samej listy "a"

przypisujemy do deck kolejną kopię tej samej listy, a.clear(), del a[:], a*=0 powodują tylko usunięcie wartości, lista pozostaje ta sama, więc b.append(a) dodaje koleją kopię tej samej listy. Rozwiązaniem jest jak sam zauważyłeś tworzenie nowej listy za każdym razem,
zapis card=[] powoduje przypisanie do zmiennej o tej samej nazwie nowej pustej listy.

 

Twój kod można zapisać też np. tak

[ on-line ]

def _make_deck() -> list:
    figures = ['A', 'K', 'Q', 'J', '10', '9', '8', '7', '6', '5', '4', '3', '2']
    colors  = ['pik', 'serce', 'trefl', 'wino']
    deck = []
 
    for col in colors:
        for fig in figures:
            card = ['', '']
            card[0] = fig
            card[1] = col
            print(card)
            deck.append(card)
            print(deck, '\n')
    return deck

_make_deck()

[ on-line ]

def _make_deck() -> list:
    figures = ['A', 'K', 'Q', 'J', '10', '9', '8', '7', '6', '5', '4', '3', '2']
    colors  = ['pik', 'serce', 'trefl', 'wino']
    deck = []
    card = []
 
    for col in colors:
        for fig in figures:
            card = [fig, col]
            print(card)
            deck.append(card)
            print(deck, '\n')
    return deck

_make_deck()

lub

[ on-line ]

def _make_deck() -> list:
    figures = ['A', 'K', 'Q', 'J', '10', '9', '8', '7', '6', '5', '4', '3', '2']
    colors  = ['pik', 'serce', 'trefl', 'wino']
    deck = []
 
    for col in colors:
        for fig in figures:
            deck.append([fig, col])
            print(deck, '\n')
    return deck

_make_deck()

lub

[ on-line ]

def _make_deck() -> list:
    figures = ['A', 'K', 'Q', 'J', '10', '9', '8', '7', '6', '5', '4', '3', '2']
    colors  = ['pik', 'serce', 'trefl', 'wino']
    deck = []
 
    for col in colors:
        for fig in figures:
            deck += [[fig, col]]
            print(deck, '\n')
    return deck

_make_deck()

no i

[ on-line ]

def _make_deck() -> list:
    figures = ['A', 'K', 'Q', 'J', '10', '9', '8', '7', '6', '5', '4', '3', '2']
    colors  = ['pik', 'serce', 'trefl', 'wino']

    return [[fig, col] for col in colors for fig in figures]

print(_make_deck())

 

Podobne pytania

0 głosów
1 odpowiedź 489 wizyt
pytanie zadane 2 grudnia 2022 w Python przez dedek2 Początkujący (370 p.)
0 głosów
1 odpowiedź 446 wizyt
pytanie zadane 14 października 2022 w Python przez Ichbinda Nowicjusz (230 p.)
0 głosów
1 odpowiedź 219 wizyt
pytanie zadane 7 września 2016 w Python przez shadou102 Pasjonat (21,690 p.)

93,327 zapytań

142,323 odpowiedzi

322,396 komentarzy

62,657 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...