Funktion verändert input-argument, ohne dass sie es soll
@Perlchamp: Genau. Bei mutablen Objekten in kopierten Datenstrukturen musst Du aufpassen. Gleiches gilt für Parameterübergaben. Bei nicht mutablen Objekten ist das unkritisch, da hier bei Änderungen stets ein neues Objekt als Resultat erzeugt wird. In Python wird alles per Referenz angesprochen, der Typ ist an das Objekt gebunden. Daher ist die Sprache sowohl dynamisch, als auch stark typisiert ("späte Typbindung"). Das ist für Umsteiger von statisch typisierten Sprachen oft etwas unheimlich. Ich empfinde dies mittlerweile als großen Vorteil und betrachte die type-annotations mit entsprechendem Argwohn. (Insbesondere die neuen Dataclasses, die type-annotations zwingend voraussetzen, gefallen mir überhaupt nicht. Aber da gehen die Meinungen sehr auseinander.)
@ _blackjack_ :
klar, wenn man weiß, was man will und vor allem, wenn man weiß, was das Programm tut und bei einer gewissenhaften Vorbereitung (OOA, OOE, OOD, OOP) muß man nicht mit Kanonen auif Spatzen schießen. Sooooo weit bin ich noch laaaaange nicht. Es ging mir bloß ums Verständnis und um's "sicher gehen" ...
@ kbr :
ja, dass der Typ an das Objekt gebunden ist, empfinde ich persönlich auch als sehr gutes "feature" und vor allen Dingen als sehr *entspannend* ...
klar, wenn man weiß, was man will und vor allem, wenn man weiß, was das Programm tut und bei einer gewissenhaften Vorbereitung (OOA, OOE, OOD, OOP) muß man nicht mit Kanonen auif Spatzen schießen. Sooooo weit bin ich noch laaaaange nicht. Es ging mir bloß ums Verständnis und um's "sicher gehen" ...
@ kbr :
ja, dass der Typ an das Objekt gebunden ist, empfinde ich persönlich auch als sehr gutes "feature" und vor allen Dingen als sehr *entspannend* ...
wer lesen kann ist klar im Vorteil
es gibt keine Probleme, sondern nur Lösungen !
Bildung ist die Freude auf mich selbst !
es gibt keine Probleme, sondern nur Lösungen !
Bildung ist die Freude auf mich selbst !
@Perlchamp: auch das flache Kopieren einer Liste ist eher selten, denn man macht meist einfach eine neue veränderte Liste, statt eine bestehende zu verändern.
Häufiger ist, dass man irgend ein iterierbares Objekt hat und daraus eine Liste machen will, da funktioniert dann nur die Variante `list(iterable)`.
Häufiger ist, dass man irgend ein iterierbares Objekt hat und daraus eine Liste machen will, da funktioniert dann nur die Variante `list(iterable)`.
@sirius3 :
... um es dann *beispielsweise* manipulieren zu können ...
... um es dann *beispielsweise* manipulieren zu können ...
Code: Alles auswählen
>>> list (“Buchstaben“)
[‘B‘, ‘u‘, ‘c‘, ‘h‘, ‘s‘, ‘t‘, ‘a‘, ‘b‘, ‘e‘, ‘n‘]
wer lesen kann ist klar im Vorteil
es gibt keine Probleme, sondern nur Lösungen !
Bildung ist die Freude auf mich selbst !
es gibt keine Probleme, sondern nur Lösungen !
Bildung ist die Freude auf mich selbst !
- __blackjack__
- User
- Beiträge: 13122
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Okay, wir sind immer noch in den 80ern aber jetzt auf dem PC – das CBM BASIC-Programm nach GW-BASIC portiert das bis MS-DOS 4 als Programmiersprache dabei war. Die speziellen Kommentare für den Basic-Boss-Compiler sind weg, dafür sind alle Integer-Variablen jetzt entsprechend mit dem % benannt um sie zu Integer-Variablen zu machen. GW-BASIC kennt Befehle für Grafik und um einzelne Zeichen abzufragen, deshalb muss nicht mehr mit PEEK/POKE/WAIT direkt auf Speicher und Hardware zugegriffen werden. IF/THEN kennt nun auch ein ELSE. Und der SWAP-Befehl macht die entsprechende Subroutine überflüssig.
Eigentlich hätte man hier auch schon was mit den Variablennamen machen können, weil GW-BASIC mehr als zwei Zeichen erlaubt. Aber da GW-BASIC Programme oft von anderen Systemen portiert waren (wie in diesem Fall) oder dorthin portiert werden sollten, war es nicht unüblich die zwei Zeichen Grenze nicht zu überschreiten. Zudem sind nur Grossbuchstaben möglich was sich Variablennamen die aus mehr als einem Wort zusammengesetzt sind, unschön liest. Und es wird schwieriger Anweisungen und Funktionen von Variablen zu unterscheiden. Man hat bei GW-BASIC ja kein Syntaxhighlighting wie hier im Forum.
Edit: Doch mal mit längeren Namen:
Code: Alles auswählen
100 RANDOMIZE -TIMER:SL%=640:SC%=350:DP=.3:MV%=5:A%=1:CD=.35
105 DIM CP%(SL%),CV%(SL%)
110 PRINT"Create and place cars...":GOSUB 5000:SCREEN 9
200 FOR Y%=0 TO SC%-1:GOSUB 500:GOSUB 1000:NEXT
210 WHILE INKEY$="":WEND:GOTO 200
500 ' ******************************
510 ' One simulation step.
520 '
530 ' 1. Update velocities.
540 FOR I%=0 TO CC%:IF I%=CC% THEN J%=0 ELSE J%=I%+1
550 V%=CV%(I%)+A%:D%=CP%(J%)-CP%(I%)-1:IF D%<0 THEN D%=D%+SL%
560 IF V%>D% THEN V%=D%
570 IF V%>MV% THEN V%=MV%
580 IF V%>=1 THEN V%=V%+(RND(1)<DP)
590 CV%(I%)=V%:NEXT
700 ' 2. Update positions.
710 FOR I%=0 TO CC%:CP%(I%)=(CP%(I%)+CV%(I%)) MOD SL%:NEXT:RETURN
1000 ' ******************************
1010 ' Plot row.
1020 '
1030 LINE (0,Y%)-(SL%,Y%):FOR I%=0 TO CC%:PRESET (CP%(I%),Y%):NEXT:RETURN
5000 ' ******************************
5010 ' Create cars.
5020 '
5030 CC%=INT(SL%*CD)-1:FOR I%=0 TO SL%-1:CP%(I%)=I%:NEXT
5040 FOR I%=0 TO SL%-1:J%=INT(RND(1)*(SL%-I%))+I%:SWAP CP%(I%),CP%(J%):NEXT
5050 F%=0:FOR I%=0 TO CC%-1:J%=I%+1
5055 IF CP%(I%)>CP%(J%) THEN F%=-1:SWAP CP%(I%),CP%(J%)
5060 NEXT:IF F% THEN 5050
5070 RETURN
Edit: Doch mal mit längeren Namen:
Code: Alles auswählen
100 RANDOMIZE -TIMER:STREET.LEN%=640:STEPCOUNT%=350:CAR.DENSITY=.35:MAX.V%=5
105 ACCEL%=1:DECEL.PROB=.3:DIM CAR.POS%(STREET.LEN%-1),CAR.V%(STREET.LEN%-1)
110 PRINT"Create and place cars...":GOSUB 5000:SCREEN 9
200 FOR Y%=0 TO STEPCOUNT%-1:GOSUB 500:GOSUB 1000:NEXT
210 WHILE INKEY$="":WEND:GOTO 200
500 ' ******************************
510 ' One simulation step.
520 '
530 ' 1. Update velocities.
540 FOR I%=0 TO CC%:IF I%=CC% THEN J%=0 ELSE J%=I%+1
550 V%=CAR.V%(I%)+ACCEL%:D%=CAR.POS%(J%)-CAR.POS%(I%)-1
555 IF D%<0 THEN D%=D%+STREET.LEN%
560 IF V%>D% THEN V%=D%
570 IF V%>MAX.V% THEN V%=MAX.V%
580 IF V%>=1 THEN V%=V%+(RND(1)<DECEL.PROB)
590 CAR.V%(I%)=V%:NEXT
700 ' 2. Update positions.
710 FOR I%=0 TO CC%
715 CAR.POS%(I%)=(CAR.POS%(I%)+CAR.V%(I%)) MOD STREET.LEN%:NEXT:RETURN
1000 ' ******************************
1010 ' Plot row.
1020 '
1030 LINE (0,Y%)-(STREET.LEN%,Y%):FOR I%=0 TO CC%
1035 PRESET (CAR.POS%(I%),Y%):NEXT:RETURN
5000 ' ******************************
5010 ' Create cars.
5020 '
5030 CC%=INT(STREET.LEN%*CAR.DENSITY)-1
5035 FOR I%=0 TO STREET.LEN%-1:CAR.POS%(I%)=I%:NEXT
5040 FOR I%=0 TO STREET.LEN%-1:J%=INT(RND(1)*(STREET.LEN%-I%))+I%
5045 SWAP CAR.POS%(I%),CAR.POS%(J%):NEXT
5050 F%=0:FOR I%=0 TO CC%-1:J%=I%+1
5055 IF CAR.POS%(I%)>CAR.POS%(J%) THEN F%=-1:SWAP CAR.POS%(I%),CAR.POS%(J%)
5060 NEXT:IF F% THEN 5050
5070 RETURN
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
- __blackjack__
- User
- Beiträge: 13122
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Dann kam mit MS-DOS 5 QBasic – Keine Zeilennummern mehr, und selbst die Sprungmarken durch die man sie ersetzen kann, braucht man nicht unbedingt, weil es Unterroutinen und Funktionen mit lokalen Variablen gibt. Variablennamen können Gross- und Kleinbuchstaben enthalten, auch wenn die nicht unterschieden werden. Aber man kann MixedCase schreiben und muss keine Punkte mehr verwenden um Worte zu trennen. Strukturierte Schleifen und IF/ELSE-Zweige die über mehr als eine Zeile gehen können. Und benutzerdefinierte zusammengesetzte Datentypen. Keine zwei Arrays mehr um die Autos zu beschreiben sondern nur noch eines bei dem jeder Eintrag ein Auto mit seinen zwei Eigenschaften beschreibt.
Code: Alles auswählen
CONST StreetLength = 640, StepCount = 480
CONST CarDensity = .35
CONST Acceleration = 1, MaxVelocity = 5, DecelerationProbability = .3
TYPE TCar
Position AS INTEGER
Velocity AS INTEGER
END TYPE
DIM i AS INTEGER
REDIM Car(0) AS TCar
RANDOMIZE -TIMER
PRINT "Create and place cars..."
CreateCars Car()
SCREEN 11
DO
FOR i = 0 TO StepCount - 1
SimulationStep Car()
PlotRow i, Car()
IF INKEY$ = CHR$(27) THEN EXIT DO
NEXT
SLEEP
LOOP UNTIL INKEY$ = CHR$(27)
SUB CreateCars (Car() AS TCar)
DIM i AS INTEGER, NewCar(StreetLength - 1) AS TCar
InitCars NewCar()
ShuffleCars NewCar()
REDIM Car(INT(StreetLength * CarDensity) - 1)
FOR i = 0 TO UBOUND(Car)
Car(i) = NewCar(i)
NEXT
SortCars Car()
END SUB
SUB InitCars (Car() AS TCar)
DIM i AS INTEGER
FOR i = 0 TO UBOUND(Car)
Car(i).Position = i
Car(i).Velocity = 0
NEXT
END SUB
FUNCTION Min% (a AS INTEGER, b AS INTEGER)
IF a < b THEN Min% = a ELSE Min% = b
END FUNCTION
SUB PlotRow (y AS INTEGER, Car() AS TCar) STATIC
DIM i AS INTEGER
LINE (0, y)-(StreetLength, y)
FOR i = 0 TO UBOUND(Car)
PRESET (Car(i).Position, y)
NEXT
END SUB
SUB ShuffleCars (Car() AS TCar)
DIM i AS INTEGER, j AS INTEGER
FOR i = 0 TO UBOUND(Car)
j = INT(RND(1) * (UBOUND(Car) + 1 - i)) + i
SWAP Car(i), Car(j)
NEXT
END SUB
SUB SimulationStep (Car() AS TCar) STATIC
DIM i AS INTEGER, j AS INTEGER
FOR i = 0 TO UBOUND(Car)
IF i = UBOUND(Car) THEN j = 0 ELSE j = i + 1
UpdateVelocity Car(i), Car(j)
NEXT
FOR i = 0 TO UBOUND(Car)
Car(i).Position = (Car(i).Position + Car(i).Velocity) MOD StreetLength
NEXT
END SUB
SUB SortCars (Car() AS TCar)
DIM i AS INTEGER, j AS INTEGER, swapped AS INTEGER
DO
swapped = 0
FOR i = 0 TO UBOUND(Car) - 1
j = i + 1
IF Car(i).Position > Car(j).Position THEN
swapped = -1
SWAP Car(i), Car(j)
END IF
NEXT
LOOP WHILE swapped
END SUB
SUB UpdateVelocity (Car AS TCar, NextCar AS TCar) STATIC
DIM Velocity AS INTEGER, Distance AS INTEGER
Velocity = Car.Velocity + Acceleration
Distance = NextCar.Position - Car.Position - 1
IF Distance < 0 THEN Distance = Distance + StreetLength
Velocity = Min(Min(Velocity, Distance), MaxVelocity)
IF Velocity >= 1 THEN
Velocity = Velocity + (RND(1) < DecelerationProbability)
END IF
Car.Velocity = Velocity
END SUB
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman