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

Problem z funkcją clear()

Object Storage Arubacloud
0 głosów
243 wizyt
pytanie zadane 16 września 2022 w Python przez kacper1445 Gaduła (4,880 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 (56,980 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 Gaduła (4,880 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 (56,980 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 Gaduła (4,880 p.)
Okej, poczytam o tym. Dzięki wielkie!
komentarz 16 września 2022 przez VBService Ekspert (253,100 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 (253,100 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ź 290 wizyt
pytanie zadane 2 grudnia 2022 w Python przez dedek2 Początkujący (370 p.)
0 głosów
1 odpowiedź 340 wizyt
pytanie zadane 14 października 2022 w Python przez Ichbinda Nowicjusz (230 p.)
0 głosów
1 odpowiedź 186 wizyt
pytanie zadane 7 września 2016 w Python przez shadou102 Pasjonat (21,630 p.)

92,555 zapytań

141,403 odpowiedzi

319,557 komentarzy

61,940 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.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...