Das kannst du dir sogar logisch/intuitiv herleiten:
In Python ist die Addition von zwei Listen als ihre Verkettung
definiert, d.h.
1
[1,2,3] + [10,20] -> [1,2,3,10,20]
Eine Multiplikation von irgendwas mit einer natürlichen Zahl n ist
nichts andere als eine wiederholte Addition des "irgendwas", also die
Summe von n "irgendwas":
Hier ist "irgendwas" die Zahl 7 und n=3:
1
7 * 3 = 7 + 7 + 7
2
= 21
Hier ist "irgendwas" die Liste [1,2,3,4]:
1
[1,2,3,4] * 3 = [1,2,3,4] + [1,2,3,4] + [1,2,3,4]
2
= [1,2,3,4,1,2,3,4,1,2,3,4]
Da spielt sich also genau das Gleiche ab wie bei Zahlen, nur dass eben
Listen anders addiert werden.
Verdammt! Bisher mussten wir uns nur mit den Unterschieden zwischen
Aristoteles Logik und weiblicher Logik herumschlagen. Jetzt kommt auch
noch Python Logik dazu.
Yalu X. schrieb:> Eine Multiplikation von irgendwas mit einer natürlichen Zahl n ist> nichts andere als eine wiederholte Addition des "irgendwas", also die> Summe von n "irgendwas":
okay, das finde ich unintuitiv. Hab mit Python bisher nur am Rande zu
tun gehabt. Ich hätte erwartet, dass er alle elemente der Liste mit 3
Multipliziert und diese Liste zurückgibt.
Vlad Tepesch schrieb:> Yalu X. schrieb:>> Eine Multiplikation von irgendwas mit einer natürlichen Zahl n ist>> nichts andere als eine wiederholte Addition des "irgendwas", also die>> Summe von n "irgendwas":>> okay, das finde ich unintuitiv. Hab mit Python bisher nur am Rande zu> tun gehabt. Ich hätte erwartet, dass er alle elemente der Liste mit 3> Multipliziert und diese Liste zurückgibt.
Klar die elementweise Multiplikation wäre ebenfalls eine sinnvolle
Möglichkeit, die Multiplikation einer Liste mit einer Zahl zu
definieren. Konsequenterweise, müsste dann aber auch die Addition zweier
Listen elementweise erfolgen. Und schon wäre das Produkt von Liste und
natürlicher Zahl wieder die Summe von n Exemplaren dieser Liste, so dass
mein oben Geschriebenes gültig bleibt :)
Ich nehme an, du bist Matlab-vorbelastet, denn dort erfolgt die Addition
und Skalarmultiplikation elementweise, so wie es für Vektoren in der
linearen Algebra gehört. Das numpy-Paket für Python macht das übrigens
für Arrays ebenso:
1
array([1,2,3,4]) * 3 -> array([3,6,9,12])
Wenn man Entsprechendes mit gewöhnlichen Listen machen will, kann man
dafür die map-Funktion verwenden:
1
map(lambda x: 3*x, [1,2,3,4]) -> [3,6,9,12]
oder
1
map(partial(mul, 3), [1,2,3,4]) -> [3,6,9,12]
Die map-Funktion liftet eine Funktion (in diesem Fall x->3*x) in die
Liste, d.h. die Funktion wird auf jedes Element angewandt.
Wem die etwas funktional angehauchte Schreibweise mit map nicht gefällt,
kann stattdessen auch List-Comprehensions verwenden:
1
[3*x for x in [1,2,3,4]] -> [3,6,9,12]
Die Addition von Strings erfolgt in Python in der gleichen Weise wie bei
Listen:
1
"apfel" + "kuchen" -> "apfelkuchen"
Entsprechend geht auch Folgendes:
1
'ha' * 3 -> 'hahaha'
Bei Strings würde die elementweise Addition und Multiplikation wenig
Sinn ergeben.
Yalu X. schrieb:> Ich nehme an, du bist Matlab-vorbelastet
erwischt ;)
Yalu X. schrieb:> map(lambda x: 3*x, [1,2,3,4]) -> [3,6,9,12]>> oder> map(partial(mul, 3), [1,2,3,4]) -> [3,6,9,12]> [... oder]> [3*x for x in [1,2,3,4]] -> [3,6,9,12]
hey, das ist ja fast wie Perl - 3 Möglichkleiten, die selbe Sache zu
erledigen und keine davon ist auf den ersten Blick verständlich ^^
Python fängt noch an mir zu gefallen *g*
Wenn du Listen elementweise addieren willst, dann willst du
wahrscheinlich keine Listen haben, sondern ein numpy.array. Das wird
elementweise addiert und kann noch viel mehr tolle Sachen.
Vlad Tepesch schrieb:> hey, das ist ja fast wie Perl - 3 Möglichkleiten, die selbe Sache zu> erledigen und keine davon ist auf den ersten Blick verständlich ^^
Nicht einmal die letzte?
Diese Schreibweise wurde eigentlich gerade deswegen als Ersatz für den
Aufruf der map- und filter-Funktion eingeführt, um die Verständlichkeit
zu verbessern, daher die Bezeichnung "List-Comprehension". Da sie zudem
auch die kürzeste der drei Alternativen ist, würde ich sie den beiden
anderen klar vorziehen.
Die map-Funktion, die Lambda-Ausdrücke und die Partial Application
wurden von Funktionalsprachen, die List-Comprehension konkret von
Haskell übernommen. Allerdings hat Python im Vergleich zu den Vorbildern
keine so geschliffene Syntax, weswegen vor allem die zweite Alternative
ziemlich holprig daherkommt.
Hier ist ein Vergleich der Schreibweisen in Python und Haskell:
1
Python: map(lambda x: 3*x, [1,2,3,4])
2
Haskell: map (\x->3*x) [1,2,3,4]
3
4
Python: map(partial(mul, 3), [1,2,3,4])
5
Haskell: map (3*) [1,2,3,4]
6
7
Python: [3*x for x in [1,2,3,4]]
8
Haskell: [3*x | x <- [1,2,3,4]]
Die List-Comprehension ist angelehnt an die beschreibende Darstellung
von Mengen in der Mathematik:
1
{ 3x | x ∈ {1,2,3,4} }
https://en.wikipedia.org/wiki/Set-builder_notation> Python fängt noch an mir zu gefallen *g*
Zurecht :)
Übrigens fallen mir in Haskell noch mindestens ein Dutzend weitere
Alternativen ein, wie man mittels eines relativ einfachen Ausdrucks eine
Liste elementweise mit einer Zahl multiplzieren kann. Damit hat Haskell
wohl eine noch höhere "Feature-Redundanz" als Python und Perl ;-)
Ein Fallstrick beim Erzeugen von listen mit dem *-operator sollte man
nicht vergessen:
1
>>> class Foo :
2
... a=0
3
...
4
>>> l=[Foo()]*3
5
>>> [x.a for x in l]
6
[0, 0, 0]
7
>>> l[0].a=1
8
>>> [x.a for x in l]
9
[1, 1, 1]
Alle Elemente der Liste referenzieren die selbe Instanz von Foo, ändert
man eine, ändern sich alle. Will man mehrere Instanzen haben, braucht
man was wie:
Vlad Tepesch schrieb:> hey, das ist ja fast wie Perl
ne. Damit das wie Perl wäre, müssten irgendwelche Sonderzeichen als
Operatoren dafür verwendet werden. Sonst könnte ja irgendein
dahergelaufener Sonntagsprogrammierer allein durch Nachdenken
draufkommen was da gemeint ist.