Python - dzialanie funkcji

0

Zastanawiam sie dlaczego ponizszy kod zmienia macierz M, skoro nie przypisuje jawnie nowej macierzy pod M ?

def dopelnienie_macierzy(_M, w, k):
    del _M[w]
    for i in range(len(_M)):
        del _M[i][k]
    return _M
    
M = [ [1,2,3], [4,5,6], [7,8,9] ]

print M
dop_M = dopelnienie_macierzy(M, 0, 0)[:]
print M

Macierz dop_M zawiera oczekiwane dane, ale nie rozumiem, dlaczego zmienia sie tez wartosc M...
Dlaczego tak sie dzieje? Jak moznaby poprawic ten kod?

0

Bo typy w pythonie są referencyjne, tzn do funkcji przekazujesz referencje/"wskaźnik" do oryginalnego obiektu a nie jego kopię. To oznacza ze zmienianie tego obiektu powoduje... jego zmianę ;] Masz tam cały czas tylko jedną jedyną listę.
Oczywiście nie możesz zmienić obiektu na który pokazuje twoja referencja poza funkcją.

def f(x):
    x = []

def g(x):
    x[0] = -1

lista = [1,2,3]
f(lista)
print(lista) # nic się nie zmienilo bo referencja w funkcji f jest tylko kopią referencji do oryginalnej listy
g(lista)
print(lista) # pierwszy element uległ zmianie, bo pracujemy cały czas na oryginalnej liście!
0

Jak nie chcesz by się zmieniało... utwórz kopię (możesz sam lub przy pomocy modułu copy)

0

Dodalem warunek na skopiowanie listy, ale dalej cos nie gra...

def dopelnienie_macierzy(M, w, k):
    _M = M[:]
    del _M[w]
    for i in range(len(_M)):
        del _M[i][k]
    return _M
0

No skopiowałeś listę, ale nie elementy tej listy, a potem robisz del właśnie na elementach. Teraz masz 2 listy, ale tylko jeden zestaw obiektów w liscie... Przykład:

class A:
    def __init__(self, v):
        self.val = v
x =A(1) # jeden obiekt
lista1 = [x] # jedna lista z naszym obiektem
lista2 = [x] # druga lista, z TYM SAMYM obiektem
lista3 = lista1[:] # kolejna lista z tym samym obiektem
print(lista1[0].val)
print(lista2[0].val)
print(lista3[0].val)
lista1[0].val = 2 # zmiana obiektu
print(lista1[0].val)
print(lista2[0].val)
print(lista3[0].val)
0

copy.deepcopy(x) Return a deep copy of x.

to chyba pomoże

0

Bo dalej nie Kopiujesz, tylko Tworzysz połączenie między referencjami; a tak wydaje się, że program robi to co Chcesz:

import copy as cp

def dopelnienie_macierzy(M, w, k):
    _M = cp.deepcopy(M)
    del _M[w]
    for i in range(len(_M)):
        del _M[i][k]
    return _M


M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

print("M: ", M)
dop_M = dopelnienie_macierzy(M, 0, 0)[:]
print("dopelnienie: ")
print(dop_M)
print("M: ", M)

Tu: https://docs.python.org/2/library/copy.html, na przykład, info o kopiowaniu.

0

Mniej wydajne propozycje z użyciem slicing i list comprehension, bez mutowania wejściowej listy

def f(_m, w, k):
    r = _m[:w] + _m[w + 1:]
    r = [line[:k] + line[k + 1:] for line in r]
    return r

def f2(_m, w, k):
    r = [line[:k] + line[k + 1:] for line in _m[:w] + _m[w + 1:]]
    return r
0

Zeby dopelnic calosc dosc istotne jest czy obiekt wewnatrz listy jest mutowalny czy tez nie jest mutowalny.
W przypadku tupli wszystko "dziala".


l1 = [3, [66, 55, 44], (7, 8, 9)]
l2 = l1[:]
l1[2] += (12, 20)
l2[2] += (10, 11)

print('l1:', l1)
print('l2:', l2)

1 użytkowników online, w tym zalogowanych: 0, gości: 1