Gå til innhold
🎄🎅❄️God Jul og Godt Nyttår fra alle oss i Diskusjon.no ×

ProgrammeringsBaren! Småprat, om det du elsker!


Anbefalte innlegg

torbøjrn: Skal innrømme at koden skrev ikke var god (kan unskylde meg litt med halveis-krav om en-bokstav-variabler i oppgaven). Koden jeg hadde så slik ut:

def foobar():
  t = ...

  def foo():
  	... t ...

  for t in ...:
  	foo()

 

Har aldri programmert seriøst i python, men de gangene jeg har programmert i python, så har jeg alltid hatt en uggen følelse av å ikke forstå helt hvordan skopet fungerer.

 

kgun: Jeg er sånn sett enig. Dersom man sier man kan python, så følger det at man skal kunne hvordan skop fungerer i python. Jeg påstår ikke å kunne python. men jeg synes det ble gjort et dårlig valg i "designet" når for-løkker ikke innfører ferske bindinger.

 

Samtidig så har python en særegen måte å håndtere variabler på, så det er sikkert mye å ta hensyn til.

 

Angående argumentet som kort oppsummert er "det er praktisk i noen tilfeller", så synes jeg det blir i baner med "det er praktisk med goto i noen tilfeller"; jeg er forsåvidt enig i begge påstanene, men det er sånn sett ikke det jeg kritiserer. For meg så brøyter for-løkken med "principle of least suprise".

Lenke til kommentar
Videoannonse
Annonse

"principle of least suprise".

Dette prinsippet er avhengig av hva man er vandt til, og således forskjellig for alle. Matz designet f.eks. Ruby etter dette prinsippet, men påpeket at han mente "least surpise for me!". Utviklere som begynte med Python/Ruby/javaScript, for så å gå videre til Java/C# ville kanskje bli svært overrasket når de oppdaget at de ikke kan benytte iterasjonsvariabelen etter at løkken var avsluttet.

Lenke til kommentar

Hva ville du tro at denne Python snutten skriver ut?

 

l = []
for i in range(5):
   l.append(lambda: i)
for f in l:
   sys.stdout.write("f returnerer " + str(f()) + "\n")

 

Hm … :hmm:

 

Uavhengig av hva slags skop for har, så er det bare én binding her. Selv om funksjonene i l lukker om i (fordi Python har closures), så vil de alle ende opp med å returnere den samme verdien. I dette tilfellet 4, ettersom range(5) returnerer [0, 1, 2, 3, 4].

 

For å få forskjellige verdier, måtte for-løkken ha laget en ny binding for hver iterasjon. I Lisp ville dette bety å omslutte løkkekroppen med (let ...). Dette ville også gjøre det umulig å tukle med tellervariabelen, dvs. løkkekroppen ville kunne inkrementere eller dekrementere i uten konsekvenser for påfølgende iterasjoner.

Endret av epsil
Lenke til kommentar

Dette prinsippet er avhengig av hva man er vandt til, og således forskjellig for alle. Matz designet f.eks. Ruby etter dette prinsippet, men påpeket at han mente "least surpise for me!".

Selvfølgelig.

 

Utviklere som begynte med Python/Ruby/javaScript, for så å gå videre til Java/C# ville kanskje bli svært overrasket når de oppdaget at de ikke kan benytte iterasjonsvariabelen etter at løkken var avsluttet.

Samtidig så vil jeg si at syntaksen i java er gangske konsistent med å vise om man gjenbruker eller introduserer en ny binding:

for (int i = 0; i < 10; i++) { 
}
System.out.println(i); /* compile-time error: i ikke i skopet */

i forhold til

int i;
for (i = 0; i < 10; i++) {
}
System.out.println(i); /* skriver ut 10 */

 

 

Hva ville du tro at denne Python snutten skriver ut?

 

l = []
for i in range(5):
   l.append(lambda: i)
for f in l:
   sys.stdout.write("f returnerer " + str(f()) + "\n")

Hm … :hmm:

 

Uavhengig av hva slags skop for har, så er det bare én binding her. Selv om funksjonene i l lukker om i (fordi Python har closures), så vil de alle ende opp med å returnere den samme verdien. I dette tilfellet 4, ettersom range(5) returnerer [0, 1, 2, 3, 4].

 

For å få forskjellige verdier, måtte for-løkken ha laget en ny binding for hver iterasjon. I Lisp ville dette bety å omslutte løkkekroppen med (let ...). Dette ville også gjøre det umulig å «tukle» med tellervariabelen, dvs. løkkekroppen kunne inkrementere eller dekrementere i uten at det fikk konsekvenser for påfølgende iterasjoner.

Her er jeg enig med deg epsi; det var ikke slik at jeg forventet at for-løkken skulle introdusere en ny binding for hver gjennomgang.

  • Liker 1
Lenke til kommentar

Hva ville du tro at denne Python snutten skriver ut?

 

l = []
for i in range(5):
   l.append(lambda: i)
for f in l:
   sys.stdout.write("f returnerer " + str(f()) + "\n")

Komprimere den litt for gøy.

>>> [f() for f in ([lambda : i for i in range(5)])]
[4, 4, 4, 4, 4]

Vet ikke om dette blåses litt opp,hører sjeldent om det vi diskuterer her med scope er noe problem i det hele tatt.

Endret av SNIPPSAT
Lenke til kommentar

Uavhengig av hva slags skop for har, så er det bare én binding her.

 

Det er korrekt. Det er ikke alltid like enkelt å skille de to, spesielt hvis man ikke har vært eksponert for språk som gjør det klart. Jeg husker ikke helt detaljene, men jeg så tilsvarende «feil» i noe GUI kode som skulle returnere callback funksjoner som laget forskjellige GUI objekter. Så ble det bare det siste objektet som ble returnert av alle funksjonene.

 

Som du sier så kan man introdusere en ny binding i Lisp med «let». I Python er det ikke like enkelt å lage en ny binding. Jeg kan tenke på en måte i koden ovenfor som ikke er spesielt elegant.

  • Liker 1
Lenke til kommentar

 

Komprimere den litt for gøy.

>>> [f() for f in ([lambda : i for i in range(5)])]
[4, 4, 4, 4, 4]

 

Kanskje du kan skrive den om slik at den lager funksjoner som returnerer [0, 1, 2, 3, 4]? Gjerne med list comprehension.

 

I Common Lisp kan man skrive:

 

(loop for f in (loop for i from 0 below 5 collect (let ((i i)) (lambda () i))) collect (funcall f))

 

Ville sannsynligvis ikke ha brukt samme navn i let, men bare for å vise at den vil gjemme den som er i scopet utenfor.

 

I Python blir det å gjøre et hack med å lage en ny funksjon som oppretter en ny binding. Hvis ingen har en mer elegant løsning?

Lenke til kommentar

Hva ville du tro at denne Python snutten skriver ut?

 

l = []
for i in range(5):
   l.append(lambda: i)
for f in l:
   sys.stdout.write("f returnerer " + str(f()) + "\n")

 

f returnerer 4

f returnerer 4

f returnerer 4

f returnerer 4

f returnerer 4

 

Ville jeg tro, ettersom det er en closure av i, ikke verdien til i. Selv om den faller ut av scope, så skal den ikke forsvinne fra closuren (det er jo derfor det heter closure).

Lenke til kommentar

f returnerer 4

f returnerer 4

f returnerer 4

f returnerer 4

f returnerer 4

 

Det er korrekt. Se også mitt svar til epsi 07:55.

 

Så er det å lage en ny binding i Python. En måte å gjøre det på er å gjøre et hack ved å lage en ekstra funksjon i mangel av noe som «let» for å lage en ny binding:

 

def hack (i):
   return (lambda: i)
l = []
for i in range(5):
   l.append(hack(i))
for f in l:
   sys.stdout.write("f returnerer " + str(f()) + "\n")

 

Jeg vet ikke om noen andre har noen bedre forslag?

 

Nå er jeg ingen Haskell ekspert, men jeg har forstått det slik at list comprehension binder iteratoren slik at i Haskell så virker det samme i motsetning til Python:

 

map ($ ()) [\y -> x | x <- [0 .. 4]]
-> [0,1,2,3,4]

 

Men det er mulig jeg blir lurt av lazy eval her? Noen Haskell eksperter her som kan svare?

Lenke til kommentar
Gjest Slettet+9871234

Der finnes ihvertfall noen her:

 

http://fp.cs.nott.ac.uk/

 

Rart med engelskmennene. Man hører ikke så mye om dem, men de har noen gode programmerings miljøre som for eksempel rundt Professor Gordon Blair http://www.comp.lancs.ac.uk/department/staff.php?name=gordon ved Lancaster universitetet. De er relativt sterke på "delegation" så vidt jeg har forstått. Delegation er relativt grundig behandlet i den "eviggrønne klassikeren":

 

Gordon Blair, John Gallagher, David Hutchison and Doug Shephard (1991): "Object Oriented Languages, Systems and Applications." Pitman Publishing ISBN 0-273-03132-5

 

Opp med hånden de som misliker følgende kode:

 

def fibonacci(max):
   a, b = 0, 1
   while a < max:
       yield a
       a, b = b, a+b

for n in fibonacci(1000000000000000000000000000000000000000000000000000000):
   print (n),

Endret av Slettet+9871234
Lenke til kommentar
Kanskje du kan skrive den om slik at den lager funksjoner som returnerer [0, 1, 2, 3, 4]? Gjerne med list comprehension.

Tjaa man kan forandre parenthese da returneres et generator object.

I forhold til list comprehension vil den da ikke uføres [0, 1, 2, 3, 4] ved hver loop.

>>> [f() for f in ((lambda : i for i in range(5)))]
[0, 1, 2, 3, 4]

>>> g = (lambda : i for i in range(5))
>>> g
<generator object <genexpr> at 0x00EFA300>

>>> l = [lambda : i for i in range(5)]
>>> l
[<function <lambda> at 0x00EF4BB0>,
<function <lambda> at 0x00E884B0>,
<function <lambda> at 0x00E88E30>,
<function <lambda> at 0x00E88F30>,
<function <lambda> at 0x00E88370>]

Endret av SNIPPSAT
Lenke til kommentar

Jeg er jo som kjent noen ganger en tut og kjør pragmatisk programmerer:

 

http://pragprog.com/book/tpp/the-pragmatic-programmer

 

Du har vel allerede et eksemplar av denne

 

http://pragprog.com/book/shcloj2/programming-clojure

 

antar jeg.

Jeg elsker PragProg-bøkene - akkurat nå leser jeg http://pragprog.com/book/tbcoffee/coffeescript

 

Anbefaler også alle å ta en titt på Pragmatic Thinking and Learning: Refactor Your Wetware. Og selvfølgelig Seven Languages in Seven Weeks: A Pragmatic Guide to Learning Programming Languages!

Lenke til kommentar
Gjest Slettet+9871234

Jeg elsker PragProg-bøkene - ...

Mange setter the pragmatic programmer som en av sine favorittbøker. Andre foretrekker kanskje O'Reilly's "Beautiful Code" http://shop.oreilly.com/product/9780596510046.do som dog bare er ratet med 4 stjerner hos O'Reilly.

 

Manning har også noen svært pedagogiske bøker, blant annet denne

 

http://www.manning.com/sande/

 

hvor en far lærer sin sønn programmering (i Python).

 

De lanserer i oktober 2011 blant annet boken: "Clojure in Action"

http://www.manning.com/rathore/

 

som du sikkert kjenner.

 

Her http://stuartsierra.com/ er en Clojure fyr du muligens må titte litt på.

 

Se også Clojure: Lisp for the Real World

 

Professionalism in programming antar jeg også at du kjenner.

 

Der finner man under "Book Reviews" en omtale av en av mine favorittbøker http://www.acceleratedcpp.com/

Endret av Slettet+9871234
Lenke til kommentar

Sitter og skrive en ekstra compiler (gjør om Expression til C) for BASIC varianten, men klør meg litt i hodet over dokumentasjonen til Microsoft på noen uttrykk.

 

Føgende funksjon:

public static UnaryExpression Quote(Expression expression)

 

A UnaryExpression that has the NodeType property equal to Quote and the Operand property set to the specified value.

Duh! Men hva ER Quote til? :S

De som skrev dette burde fått fik for å kaste bort tid ved å skrive en fullstendig verdiløs forklaring på hva funksjonen gjør. Faktisk er hele dokumentasjonen på System.Linq.Expressions ganske mangelfull.

Lenke til kommentar

Jeg får ikke til å bruke math-funksjoner i Python. Jeg prøver bare å skrive print(math.floor(1.5)) for eksempel, men da får jeg bare en standard feilmelding om at det ligger en feil i første linje.

 

Må jeg importere et bibliotek eller noe tilsvarende?

 

Jeg bruker python 3.2.

 

Jeg har funnet denne dokumentasjonen som sier at denne modulen alltid er tilgjengelig:

 

http://docs.python.org/py3k/library/math.html#module-math

 

EDIT: Jeg har også prøvd i python 2.7, og selv om det står eksplisitt i dokumentasjonen til begge at modulen skal være bygget inn så fungerer ingen matte-funksjoner. Hva er det jeg mangler? Det står bare at floor/ceil/exp ikke er "defined"..

Endret av haarod
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...