6 svar
286 visningar
Hondel Online 1289
Postad: 16 apr 2021 17:26 Redigerad: 16 apr 2021 17:27

Pekare (?) i Python

Hallå Python lovers!

Hur fungerar det här med pekare i Python egentligen? Jag lär mig Python lite ad hoc och har därför troligtvis en del grundläggande luckor. Om min kod ser ut såhär:

def foo(i):
    my_list_modified = my_list
    for x in my_list_modified:
        if condtion:
            my_list_modified.remove(x)
    #  Gör lite mer grejer

my_list = [1,2,3,4]
for i in range(25):
    foo(i)

Kommer då my_list att förändras när jag kallar foo?

Om jag istället skickar med my_list som argument till foo såhär:

def foo(i, my_list_foo):
    my_list_modified = my_list_foo
    for x in my_list_modified:
        if condtion:
            my_list_modified.remove(x)
    #  Gör lite mer grejer

my_list = [1,2,3,4]
for i in range(25):
    foo(i, my_list)

då kommer den lämnas oförändrad?

Det var ett tag sedan jag programmerade i C++, men där är jag rätt säker på att man kunde skicka argument som värden eller som referenser, hur fungerar det egentligen i Python?

Egentligen blir det kanske två frågor här, men känns som att båda är relaterade till pekare 1) när jag skriver my_list_modified = my_list och sedan använder remove() på my_list_modified, påverkar det även my_list? och 2) hur fungerar det med argument, förändras deras värde utanför funktionen om jag ändrar dem inuti?

Laguna 28468
Postad: 16 apr 2021 21:47

my_list kommer att förändras i båda fallen. Om man vill göra en kopia av ett objekt kan man använda funktionerna i modulen 'copy'. Man kan kopiera antingen allt i objektet eller bara översta nivån. För en lista kan man göra my_list_copy = my_list[:].

Hondel Online 1289
Postad: 17 apr 2021 09:24

Hm, okej.

För vilka objekt behövs .copy()? Jag menar, om det hade varit ints istället, hade samma sak skett då?

Dum följdfråga: när skulle man då ens använda my_list_modified = my_list ? Jag menar, varför skulle jag någonsin kopiera listan och göra ändringar på my_list_modified, när ändringarna ändå slår igenom på my_list, då kan jag ju bara göra ändringarna direkt på my_list? 

Laguna 28468
Postad: 17 apr 2021 10:02

Enkla objekt, som int, behöver inte kopieras. Om man skickar dem som argument så kan inte funktionen modifiera dem så att det märks hos anroparen (man kan inte välja att anropa med värde eller referens, som i C++, och explicita pekaroperationer finns inte).

En del sammansatta objekt är inte modifierbara, t.ex. tupler och strängar, och dessa behöver man inte heller kopiera.

Man kanske inte vill ändra originallistan, utan producera en kopia. Eller ändringarna kanske inte är så enkla, så man behöver ha originallistan kvar medan man arbetar.

Hondel Online 1289
Postad: 17 apr 2021 21:19

Okej, jag inser att min formulering gav upphov till missförstånd:

Jag förstår varför man skulle göra my_list_modified = my_list.copy(). Det jag inte förstår är när my_list_modified = my_list (dvs utan att använda copy) skulle vara användbart. Alltså, i det senare fallet får jag två objekt som är exakt lika, och ändrar jag den ena så ändras även den andra? Det låter för mig helt oanvändbart och endast onödigt. Så, varför behövs copy används explicit, varför är inte det "default" (eftersom att som läget är nu ser jag ingen användning att INTE använda copy).

Jag skriver inte ofta frågor på Pluggakuten, men ändå har 1/3 av dem handlat om att jag inte använt copy när jag vill ha en kopia på ett objekt, så det är uppenbarligen något i grundkonceptet jag inte fattar..... :D

Dr. G 9326
Postad: 17 apr 2021 23:52
Hondel skrev:

Jag förstår varför man skulle göra my_list_modified = my_list.copy(). Det jag inte förstår är när my_list_modified = my_list (dvs utan att använda copy) skulle vara användbart. Alltså, i det senare fallet får jag två objekt som är exakt lika, och ändrar jag den ena så ändras även den andra? Det låter för mig helt oanvändbart och endast onödigt. Så, varför behövs copy används explicit, varför är inte det "default" (eftersom att som läget är nu ser jag ingen användning att INTE använda copy).

Bytte själv från matlab/octave till python för ett par år sedan och har många gånger gått i fällan 

A = B 

istället för 

A = B.copy()

Har inte heller fattat vitsen med varför python gör som det gör. 

Skaft 2373 – F.d. Moderator
Postad: 18 apr 2021 10:42

Det finns en gammal Python-guru som bloggat om detta. Den sammanfattade förklaringen är att tilldelningar alltid skapar referenser ("pekare"), snarare än kopior. Och:

The alternative would be for assignment to copy values, and that would make your programs unbearably slow.

Som jag uppfattar saken handlar det alltså inte om att man "ofta vill" ha två variabelnamn på samma lista och därför har det som default, utan att grundbeteendet "skapa pekare, inte kopior" är mer effektivt.

Svara Avbryt
Close