mam problem z pythonem
w skrocie mam wlasna funkcje w ktorej mam petle i w tejze petli
odwoluje sie do tej samej funkcji, i mam problem z zmienna nr
[code]
def bRun(val, name, bf, res, bfpt, info, mlt, pr, nr = {0:1}, check =
False):
solutions = {}
new, cz = runF(val, name, bf, res, check)
solt = oneTab(new)
lst = nr.keys()[-1]
last = glMulti(nr)
if solt["e"] > 0 and last < mlt:
m = 1
solutions[lst] = {"data" : solt, 'mlt' : last}
tmp = newName(name, nr, True)
if len(nr) == 1:
fwrite("dane.%s.dat" % tmp, info, {"dat":val,"UZR" : "{5: %s}" %
bf})
else:
fwrite("dane.%s.dat" % tmp, info, {'ISW' : -1, 'NTST' : 1000,
'IRS' : 1, 'UZR' : '{5 : %s}' % bf})
perLoop = periodInfo(cz, bfpt, last)
if len(perLoop) > 0:
solutions[lst]["next"] = {}
step = 1
for i in perLoop:
var = getSelectData(val, i)
nr[lst + 1] = perLoop[i][0]
last = glMulti(nr)
if last < mlt and lst < 3:
tmp = newName(name, nr)
multiPerVar(var, pr, tmp, last)
tmpNr = nr
solutions[lst]["next"][step] = bRun(val, tmp, bf, res, bfpt,
info, mlt, pr, tmpNr, "rtbp2")
step += 1
if len(solutions[lst]["next"]) == 0:
del solutions[lst]["next"]
return solutions
[/code]
nie wiem jak to porzadnie wytlumaczyc, wiec sprobuje to wytlumaczyc na
tym przykladzie
wiec zalozmy po pierwszym wywolaniu zmienna perLoop ma dwie zmienne,
wiec petla sie wykona dwukrotnie, pierwsze wykonanie oznaczmy A a
drugie B, teraz wykonujac A znajdujemy ze zmienna nr ma postac, {0:
1], i nowe perLoop ma 3 zmienne ktore wykonujemy i tam zmienna ma
postac {0:1, 1:x}
i tu spelniaja sie warunki ktore uniemozliwiaja mi kolejne wywolanie
funkcji bRun wiec wracam do elementu B
ale niestety tutaj napotykam problem, gdyz wg. mnie zmienna nr powinna
miec teraz postac {0:2} natomiast to co otrzymuje to jest {0:2, 1:x}
jesce zanim znajde czy nowy perLoop ma jakies elementy,
z tego wnioskuje ze zmienna nr nie jest zmienna lokalna, czego
zupelnie nie rozumiem, gdyz myslalem
ze zmienne w funkcji sa lokalne, a tu widze na swoim przykladzie ze
tak nie jest, bo gdyby tak bylo to zmienna nr po wykonaniu A i
kolejnych wywolaniach bRun powinna miec postac {0:1,1:x,....} ale w
momencie jak startuje z B powinna miec postac {0:2}
mam nadzieje ze mnie ktos zrozumie i wytlumaczy mi gdzie zle mysle,
lub gdzie popelnilem blad
dzieki za wyrozumialosc, pewnie cos tu bedzie nie zrozumiale wiec
pytajcie moze
uda mi sie jakos inaczej rozjasnic o co mi chodzi
W Pythonie nazwy obiektów to nie to co obiekty. W powyższym kodzie nr i
tmpNr to różne nazwy tego samego obiektu. Jak chcesz mieć inny obiekt
to go musisz gdzieś utworzyć.
Zamiast bezskutecznego kombinowania z tmpNr zmień wołanie
solutions[lst]["next"][step] = bRun(val, tmp, bf, res, bfpt, info, mlt,
pr, tmpNr, "rtbp2")
na:
solutions[lst]["next"][step] = bRun(val, tmp, bf, res, bfpt, info, mlt,
pr, dict(nr), "rtbp2")
Ogólnie:
Generalnie wyróżnia się 4 (w miarę typowych) semantyk (sposobów)
gorliwego (tj. nie leniwego) przekazywania parametrów...
Zakładamy że mamy funkcję:
fun(a, b, t, u):
print a, b, t[0], u[1]
tmp = a
a = b
b = tmp
t[0] = 13
u[1] = 19
oraz kod ją wołający
a = 10
b = 20
tab = [7, 5]
fun(a, b, tab, tab)
print a, b, tab[0], tab[1]
1. Przez wartość -- lokalnie tworzone są nowe zmienne do których
kopiowane są przekazane w wołaniu wartości -- ww. kod wypisze :
10 20 7 5
10 20 7 5
2. Przez zmienną -- w parametrze przekazuje się (referencję na) zmienną,
niejako tworzy się alias przekazywanej zmiennej, wszelkie zmiany
parametru, łącznie z przypisaniem są widoczne na zewnątrz funkcji -- ww.
kod wypisze:
10 20 7 5
20 10 13 19
3. Przez kopię -- lokalnie tworzone są nowe zmienne do których kopiowane
są przekazane w wołaniu zmienne (czyli tak w 1.), ale na zakończenie
działania funkcji wartości tych lokalnych zmiennych utworzonych wg
parametrów są kopiowane z powrotem do przekazanych w wołaniu zmiennych;
kłopot taki że jak się przekaże 2 razy tę samą zmienną to mogą być
"zabawne" efekty -- ww. kod wypisze:
10 20 7 5
20 10 7 19
lub
10 20 7 5
20 10 13 5
zależnie od kolejności kopiowania parametrów na zakończenie funkcji
4. Przez obiekt -- odróżniamy nazwę zmiennej (obiektu) od jej wartości,
lokalnie powstaje nowa nazwa, dowiązane do nowego obiektu, czyli
podobnie do 2. ale lokalne przypisanie nie jest widoczne na zewnątrz,
tylko lokalna mutacja jest -- ww. kod wypisze:
10 20 7 5
10 20 13 19
Python używa właśnie 4 sposobu
Podsumowując:
zakłądałeś, że Python używa 1. sposobu a on używa 4.
pzdr
\SK
--
"Never underestimate the power of human stupidity" -- L. Lang
--
http://www.tajga.org -- (some photos from my travels)
Dżizas, startujesz w jakimś konkursie na obfuskowanie kodu?
> z tego wnioskuje ze zmienna nr nie jest zmienna lokalna, czego
> zupelnie nie rozumiem, gdyz myslalem
> ze zmienne w funkcji sa lokalne, a tu widze na swoim przykladzie ze
> tak nie jest, bo gdyby tak bylo to zmienna nr po wykonaniu A i
> kolejnych wywolaniach bRun powinna miec postac {0:1,1:x,....} ale w
> momencie jak startuje z B powinna miec postac {0:2}
Domyślne wartości w deklaracji funkcji są ewaluowane *raz*, podczas
parsowania funkcji.
Domyślna wartość, która jest typem mutowalnym będzie wskazywała na *tę
samą instancję*, a nie tworzyła nową.
def f(x=[]):
x.append(len(x))
print x
f()
f()
f()
Standardowym trikiem jest np.
def f(x=None):
if(x is None):
x = []
btw. inny przykład niezbyt mądrego użycia typu mutowalnego
x = [[]]*10
x[0].append('a')
print x
<snip>
Kod wrzuciłem sobie na http://gist.github.com/288844 żeby łatwiej było
go przeczytać.
> nie wiem jak to porzadnie wytlumaczyc, wiec sprobuje to wytlumaczyc na
> tym przykladzie
>
> wiec zalozmy po pierwszym wywolaniu zmienna perLoop ma dwie zmienne,
Zakładam, że chodzi ci o listę, która ma dwa elementy (wyrażenie
"zmienna ma dwie zmienne" nie opisuję dobrze sytuacji).
> wiec petla sie wykona dwukrotnie, pierwsze wykonanie oznaczmy A a
> drugie B, teraz wykonujac A znajdujemy ze zmienna nr ma postac, {0:
> 1}, i nowe perLoop ma 3 zmienne ktore wykonujemy i tam zmienna ma
> postac {0:1, 1:x}
Nigdzie pomiędzy liniami 23-34 nie widzę, żeby perLoop się jakkolwiek
zmieniało, więc nie wiem skąd miało by mieć nagle 3 elementy.
> i tu spelniaja sie warunki ktore uniemozliwiaja mi kolejne wywolanie
> funkcji bRun wiec wracam do elementu B
> ale niestety tutaj napotykam problem, gdyz wg. mnie zmienna nr powinna
> miec teraz postac {0:2} natomiast to co otrzymuje to jest {0:2, 1:x}
> jesce zanim znajde czy nowy perLoop ma jakies elementy,
Jeśli przekazałeś słownik, który jest pod zmienną nr, do jakieś
funkcji, to ta funkcja może zmienić ten słownik. Nie może zmienić
twojej zmiennej - nr nadal będzie wskazywać na ten sam słownik, ale to
nie znaczy, że ten słownik się nie zmieni. Mówiąc bardziej fachowo: w
Pythonie zmienne są tylko nazwami wskazującymi na obiekty, a
przekazywanie argumentów odbywa się przez przekazanie kopii wskaźnika,
a nie kopii całego obiektu.
Drugi aspekt, to taki, że argumenty domyślne są tworzone tylko raz.
Łatwo prowadzi to do pułapki, jeśli się tam poda obiekt, który może
zmienić stan. Na przykład:
def dodaj_5(lista=[]):
lista.append(5)
return lista
print dodaj_5() # [5]
print dodaj_5() # [5,5]
> z tego wnioskuje ze zmienna nr nie jest zmienna lokalna, czego
> zupelnie nie rozumiem, gdyz myslalem
> ze zmienne w funkcji sa lokalne, a tu widze na swoim przykladzie ze
> tak nie jest, bo gdyby tak bylo to zmienna nr po wykonaniu A i
> kolejnych wywolaniach bRun powinna miec postac {0:1,1:x,....} ale w
> momencie jak startuje z B powinna miec postac {0:2}
>
> mam nadzieje ze mnie ktos zrozumie i wytlumaczy mi gdzie zle mysle,
> lub gdzie popelnilem blad
> dzieki za wyrozumialosc, pewnie cos tu bedzie nie zrozumiale wiec
> pytajcie moze
> uda mi sie jakos inaczej rozjasnic o co mi chodzi
Twój kod ogólnie jest bardzo chaotyczny, a nazwy zmiennych i funkcji
bardzo mało informujące. Funkcja, która przymuję 8 argumentów, to nie
funkcja tylko zgroza - nie wierze, że pamiętasz ich kolejność bez
patrzenia na definicję. Znalazło by się też kilka innych uwag, jak
np. lst = nr.keys()[-1] <- to wygląda jakbyś zakładał, że da ci to
ostatnio wstawiony klucz albo coś w tym stylu, podczas gdy kolejność
kluczy w słowniku jest *nieustalona*.
ok, to w takim razie zeby po wykonaniu sie bRun z linii 31, slownik nr
nie zawieral elementow ktore zostaly zapisane w bRun
to co musialbym zrobic? wlasnie myslalem ze moze wprowadzenie nowej
zmiennej tmpNr sprawi, ze po wykonaniu bRun slownik
nr bedzie mial tyle elementow co przed wywolaniem bRun
> Twój kod ogólnie jest bardzo chaotyczny, a nazwy zmiennych i funkcji
> bardzo mało informujące. Funkcja, która przymuję 8 argumentów, to nie
> funkcja tylko zgroza - nie wierze, że pamiętasz ich kolejność bez
> patrzenia na definicję. Znalazło by się też kilka innych uwag, jak
> np. lst = nr.keys()[-1] <- to wygląda jakbyś zakładał, że da ci to
> ostatnio wstawiony klucz albo coś w tym stylu, podczas gdy kolejność
> kluczy w słowniku jest *nieustalona*.
no oczywiscie ze musze sprawdzac w definicji kolejnosc, ale co mam
zrobic, skoro tak duzo zmiennych potrzebuje,
moge wprawdzie, w definicji bRun za kazdym razem jak ja wywoluje
obliczac te dane, ale to chyba szkoda czasu
acha, czyli nie da sie wyciagnac ostatniego wstawionego klucza?
> > Twój kod ogólnie jest bardzo chaotyczny, a nazwy zmiennych i funkcji
> > bardzo mało informujące. Funkcja, która przymuję 8 argumentów, to nie
> > funkcja tylko zgroza - nie wierze, że pamiętasz ich kolejność bez
> > patrzenia na definicję. Znalazło by się też kilka innych uwag, jak
> > np. lst = nr.keys()[-1] <- to wygląda jakbyś zakładał, że da ci to
> > ostatnio wstawiony klucz albo coś w tym stylu, podczas gdy kolejność
> > kluczy w słowniku jest *nieustalona*.
> acha, czyli nie da sie wyciagnac ostatniego wstawionego klucza?
Nie, bez dodatkowej zmiennej nie da się. Słownik jest tablicą
haszującą.
pozdrawiam
p.s.
Źle zrozumiałeś.
Przypisanie nie będzie widoczne na zewnątrz. Ciągle mylis zobiekt i jego
nazwę, przypisanie to jest "podpięcie" nazwy pod obiekt. Na zewnątrz za
to widoczne będą zmiany w przekazanych obiektach. Czyli jak masz
def foo(lista=[]):
lista.append('bar')
print lista
print 'pierwsze:'
foo()
print 'drugie:'
foo()
print 'trzecie:'
foo([])
print 'czwarte:'
foo()
to wynikiem będzie...
pierwsze:
['bar']
drugie:
['bar', 'bar']
trzecie:
['bar']
czwarte:
['bar', 'bar', 'bar']
Natomiast wynik tego...
def foo(lista=[]):
lista = ['baz']
print lista
print 'pierwsze:'
foo()
print 'drugie:'
foo()
print 'trzecie:'
foo([])
print 'czwarte:'
foo()
będzie...
pierwsze:
['baz']
drugie:
['baz']
trzecie:
['baz']
czwarte:
['baz']
Bo w pierwszym przypadku zmieniamy obiekt z listą a w drugim przed
zmianą pod nazwę lista podpinamy nowy obiekt stary (ten z parametru)
zostawiając w spokoju.