Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: J. Ghibulo 04. 10. 2016, 10:17:40
-
Zdravím, trochu si hraju s Pythonem a vrtá mi hlavou, proč...
def funkce(lst):
lst = lst[1:]
return lst
a = [1,2,3]
b = funkce(a)
vyhodí toto:
a= [1, 2, 3]
b= [2, 3]
a naopak, když klíčový řádek nahradím:
lst.pop(0)
tak to vyhodí kýžené:
a= [2, 3]
b= [2, 3]
V céčku i javě dokážu na základě znalosti principu snadno předvídat chování a protože se u Pythonu musím pořád ujišťovat, tak mi zřejmě něco důležitého uniká :-[ :)
-
Zdravím, trochu si hraju s Pythonem a vrtá mi hlavou, proč...
def funkce(lst):
lst = lst[1:]
return lst
a = [1,2,3]
b = funkce(a)
vyhodí toto:
a= [1, 2, 3]
b= [2, 3]
a naopak, když klíčový řádek nahradím:
lst.pop(0)
tak to vyhodí kýžené:
a= [2, 3]
b= [2, 3]
V céčku i javě dokážu na základě znalosti principu snadno předvídat chování a protože se u Pythonu musím pořád ujišťovat, tak mi zřejmě něco důležitého uniká :-[ :)
protoze lst[1:] nema vliv na hodnotu lst. Pak vysledek jenom priradis do te same promenne, ale samotna puvodni reference je netknuta.
Ad s volani odkazem nebo hodnotou bude mit ten prvni priklad stejny vysledek (rozdilne by bylo nejspis jen velmi obskurni volani jmenem)
-
Ahoj,
V jave to funguje uplne stejne, proste si predstav, ze lst[1:] je syntakticky cukr pro volani funkce, ktera vrati novou instanci listu (nebo tuple) s pozadovanymi prvky.
-
s pythonem už nějakou dobu nedělám, ale řekl bych, že něco jako int* a = ...; *a = 10; v pythonu prostě napsat nejde, vždycky jen a = ...
-
Pro OP:
Muzes si to predstavit tak, ze do funkce se predava ukazatel na objekt:
void f(Objekt* o) {
o.a = 1; // muzes zmenit stav objektu (zmenit objekt "uvnitr")
o = o2; // ale nemuzes ho vymenit za jiny (zmena se ti neprojevi vne funkce)
}
...cili si musis uvedomit, co predavas a jak s tim operujes - vysledek se totiz podle toho lisi.
s pythonem už nějakou dobu nedělám, ale řekl bych, že něco jako int* a = ...; *a = 10; v pythonu prostě napsat nejde, vždycky jen a = ...
Takhle naprimo ne. Ale pokud toho mermomoci chces dosahnout, staci pouzit drobny hack:
>>> def f(l):
... l[0] = 1
...
>>> l = [2]
>>> f(l)
>>> l
[1]
-
Ahoj,
V jave to funguje uplne stejne, proste si predstav, ze lst[1:] je syntakticky cukr pro volani funkce, ktera vrati novou instanci listu (nebo tuple) s pozadovanymi prvky.
To neni podstata toho problemu, co OP popisuje. Podstatou je, ze nemuze zmenit lst tak, aby se to projevilo vne funkce.
Parametry se proste v pythonu predavaji hodnotou, pricemz hodnotou je bud adresa objektu nebo primo vlastni skalar (aka "call by assignment").
-
Jeste asi nejlepsi ilustrace (a pak uz mlcim ;) ):
>>> def g(x):
... print id(x)
... x = [1,2,3]
... print id(x)
...
>>> l = [1]
>>> id(l)
34367528904 <------ adresa objektu "[1]" vne funkce
>>> g(l)
34367528904 <------ do "x" uvnitr fce se priradi ("assign") stejny objekt "[1]"
34367570000 <------ tady uz mam v "x" prirazeny jiny objekt ("[1,2,3]") - ale jenom jsem LOKALNE uvnitr "f" zmenil prirazeni x (vlozil jsem do nej lokalne jiny objekt)
>>> id(l)
34367528904 <------ vne funkce zustava "l" porad stejne
>>> l <------ ...a timpadem ma i porad stejnou hodnotu
[1]
-
Ahoj,
V jave to funguje uplne stejne, proste si predstav, ze lst[1:] je syntakticky cukr pro volani funkce, ktera vrati novou instanci listu (nebo tuple) s pozadovanymi prvky.
To neni podstata toho problemu, co OP popisuje. Podstatou je, ze nemuze zmenit lst tak, aby se to projevilo vne funkce.
Parametry se proste v pythonu predavaji hodnotou, pricemz hodnotou je bud adresa objektu nebo primo vlastni skalar (aka "call by assignment").
Viz druhý příklad. Protože se hodnotou předává reference na mutable list.
-
Viz druhý příklad. Protože se hodnotou předává reference na mutable list.
a?
-
Doporucuju se (v Pythonu) vykaslat na koncept "hodnotou" a "odkazem". V Pythonu jsou vsechny "promenne" jenom jmena (s lokalni nebo nelokalni platnosti), ktera odkazuji na nejake objekty v pameti. Ty objekty jsou nebo nejsou mutovatelne a podle toho se s nimi da zachazet. Tudiz se muzes v tech svych prikladech se uplne oprosti od toho, ze volas funkci - to je uplne jedno, ty jenom lokalni promenne (jmenu) uvnitr funkce prirazujes ten objekt, pak v te funkci delas jine veci a pak, pripadne nejakemu jinemu jmenu prirazujes objekt, ktery funkce vraci. Tudiz
def funkce(lst):
lst = lst[1:]
return lst
a = [1,2,3]
b = funkce(a)
lze bez jakehokoli premysleni prepsat na
a = [1,2,3]
b = a[1:]
a
def funkce(lst):
lst.pop(0)
return lst
a = [1,2,3]
b = funkce(a)
prepises mentalne na
a = [1,2,3]
a.pop(0)
b = a
Slice dela novy seznam, pop() modifikuje existujici, vsechno ostatni je jenom prirazovani nejakeho objektu nejakemu jmenu - z logickeho hlediska tam nic jineho neni, fyzicky samozrejme volani funkce ma nejakou rezii apod., ale pro pochopeni to je irelevantni. Vykasli se na predavani hodnotou a odkazem a vsechno ti docvakne.
-
Zdravím, trochu si hraju s Pythonem a vrtá mi hlavou, proč...
def funkce(lst):
lst = lst[1:]
return lst
Příkazem lst = lst[1:] vzniká nový objekt lst, který s původním objektem lst již nemá nic společného. Původní objekt se touto operací stane pro funkci nedostupným.
-
Super - díky všem :)... začíná docvakávat 8)