[nbviewer] Ebenfalls veröffentlicht unter (http://nbviewer.jupyter.org/format/slides/github/y-sama/comprehension/blob/master/comprehension.ipynb#/).
Apropos Python, es ist eine inklusive Notation. <= Vorurteile? Es ist jedoch schwierig zu lesen, wenn man sich nicht daran gewöhnt hat. Deshalb habe ich versucht, das Lesen etwas detaillierter zusammenzufassen.
extension_1 = []
for i in range(10):
extension_1.append(i)
extension_1
#>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Grundlegende Syntax [counter for counter in iterator] Ich schreibe oft zuerst nur [i für i in] und ändere es dann. Beim Generieren einer Liste, die der Erweiterung_1 in Einschlussnotation entspricht
comprehension_1= [i for i in range(10)]
comprehension_1
#>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Vergleichen wir die Ausführungsgeschwindigkeit, ob die Listeneinschlussnotation verwendet werden soll. Es wurde unter Verwendung von Jupyters Zellmagie %% timeit gemessen.
%%timeit
extension_1 = []
for i in range(10000):
extension_1.append(i)
#>>> 100 loops, best of 3: 3.37 ms per loop
%%timeit
comprehension_1= [i for i in range(10000)]
#>>> 1000 loops, best of 3: 1.05 ms per loop
** Die Aufnahme von Listen macht den Code nicht nur sauberer, sondern hat auch einen Vorteil in Bezug auf die Geschwindigkeit ** Referenz: Warum ist Pythons Einschlussnotation so schnell? Es gibt zwei Hauptgründe, langsam zu sein.
Der erstere Effekt kann auch beseitigt werden, indem die Referenz aus der Schleife gedrückt wird.
%%timeit
extension_1_ = []
append=extension_1_.append
for i in range(10000):
append(i)
#>>> 1000 loops, best of 3: 1.57 ms per loop
Es wird allgemein gesagt, dass die Ausführungsgeschwindigkeit verdoppelt wird, wenn die Liste enthalten ist, aber ungefähr 80% davon sind auf den Overhead des Aufrufteils der Append-Methode zurückzuführen.
Es gibt keine Postfix if-Anweisung in Python, aber Sie können (als Ergebnis) nur die Listeneinschlussnotation schreiben.
extension_2 =[]
for i in range(10):
if i%2==0:
extension_2.append(i)
extension_2
#>>> [0, 2, 4, 6, 8]
Wenn Sie extension_2 in Listeneinschlussnotation umschreiben, sieht es folgendermaßen aus.
comprehension_2 = [i for i in range(10) if i%2==0]
comprehension_2
#>>> [0, 2, 4, 6, 8]
Das Ergebnis ist eine Postfix-If-Syntax, da die Inklusivnotation eine for-Klausel gefolgt von einer if-Klausel oder einer for-Klausel enthält. (Stellen Sie sich vor, Sie können den Doppelpunkt und den Einzug weglassen.)
Mit Einrückung ist das Bild wie folgt.
[
i
for i in range(10)
if i%2==0
]
Ich werde dies in Dark Edition etwas ausführlicher erläutern. ..
%%timeit
extension_2 =[]
for i in range(10000):
if i%2==0:
extension_2.append(i)
#>>> 100 loops, best of 3: 4.08 ms per loop
%%timeit
comprehension_2 = [i for i in range(10000) if i%2==0]
#>>> 100 loops, best of 3: 3.15 ms per loop
%%timeit
extension_2_ =[]
append=extension_2_.append
for i in range(10000):
if i%2==0:
append(i)
#>>> 100 loops, best of 3: 3.81 ms per loop
** Wenn die Berechnungsrate bestimmt wird, verbessert sich die Geschwindigkeit nur um etwa 20 bis 30%, selbst wenn Sie die Listeneinschlussnotation erzwingen. ** **.
Es ist verwirrend, aber ** wenn es eine else-Klausel enthält, ändert sich die Position von if, weil der bedingte Operator (mit anderen Worten der ternäre Operator) verwendet wird ** (Bedingte Operatoren werden erst nach Python 2.5 unterstützt.)
extension_3 =[]
for i in range(10):
if i%2==0:
extension_3.append(i)
else:
extension_3.append(str(i))
extension_3
#>>> [0, '1', 2, '3', 4, '5', 6, '7', 8, '9']
comprehension_3 = [ i if i%2==0 else str(i) for i in range(10)]
comprehension_3
# >>> [0, '1', 2, '3', 4, '5', 6, '7', 8, '9']
Es ist möglicherweise einfacher zu verstehen, wenn Sie der Meinung sind, dass dies tatsächlich gleichwertig ist
extension_3_cond =[]
for i in range(10):
extension_3_cond.append(i) if i%2==0 else extension_3_cond.append(str(i))
extension_3_cond
#>>> [0, '1', 2, '3', 4, '5', 6, '7', 8, '9']
Ich erhalte eine Fehlermeldung, wenn ich if ~ else hinzufüge, nachdem ich durch das Schreiben eines Postfixes if gezogen wurde.
#Funktioniert nicht
[ i for i in range(10) if i%2==0 else str(i)]
#>>> SyntaxError: invalid syntax
Da, wenn ~ else ratenbestimmend ist, die Einschlussnotation nicht viel beschleunigt.
In Python2.7 oder höher können Wörterbucheinschlüsse und Satzeinschlüsse auch als andere Einschlussnotationen als Listen verwendet werden.
comprehension_dict = {str(i):i for i in range(10)}
print(comprehension_dict)
#>>> {'7': 7, '8': 8, '2': 2, '9': 9, '0': 0, '1': 1, '6': 6, '5': 5, '4': 4, '3': 3}
Es passt gut zum Reißverschluss.
label = ["kinoko", "takenoko", "suginoko"]
feature = ["yama", "sato", "mura"]
{i:j for i,j in zip(label,feature)}
#>>> {'kinoko': 'yama', 'suginoko': 'mura', 'takenoko': 'sato'}
Wenn Sie den Schlüssel und den Wert einfach wie in diesem Fall übergeben, müssen Sie die Einschlussnotation nicht verwenden.
dict(zip(label,feature))
Bis zu Python2.6 werde ich Tupel zum Diktieren übergeben.
comprehension_dict2 = dict((str(i),i) for i in range(10))
print(comprehension_dict2)
Sie können auch postfix verwenden, wenn.
comprehension_dict2 = {str(i):i for i in range(10) if i%2==0}
print(comprehension_dict2)
#>>> {'8': 8, '6': 6, '2': 2, '4': 4, '0': 0}
Sie können auch bedingte Operatoren verwenden. Da es sich um einen bedingten Operator handelt, muss er in jedem Schlüssel und Wert vor und nach dem ":" beschrieben werden.
comprehension_dict3 = {str(i) if i%2==0 else i : i if i%2==0 else str(i) for i in range(10)}
print(comprehension_dict3)
#>>> {'2': 2, 1: '1', 3: '3', 5: '5', '0': 0, 7: '7', 9: '9', '6': 6, '4': 4, '8': 8}
Das funktioniert nicht. (Ich habe es vor orz gemacht)
#Funktioniert nicht
comprehension_dict4 = {str(i):i if i%2==0 else i:str(i) for i in range(10)}
#>>> SyntaxError: invalid syntax
Wenn Sie es in {} ohne Doppelpunkt einschließen, wird es in den Satz aufgenommen.
comprehension_set={i%5 for i in range(10)}
comprehension_set
#>>> {0, 1, 2, 3, 4}
Beachten Sie, dass {} mit null Elementen ein Wörterbuch bedeutet.
zero_set={}
type(zero_set)
# >>> dict
Es ist leicht, die Syntax falsch zu verstehen, aber selbst wenn Sie sie in () einschließen, handelt es sich um einen Generatorausdruck anstelle einer Taple-Einschlussnotation.
comprehension_gen=(i%5 for i in range(10))
comprehension_gen
#>>> <generator object <genexpr> at 0x7f3000219678>
for i in comprehension_gen:print(i)
#>>> 0
#>>> 1
#>>> 2
#>>> 3
#>>> 4
#>>> 0
#>>> 1
#>>> 2
#>>> 3
#>>> 4
Es wird eher anstelle der Tupeleinschlussnotation verwendet. Im Gegensatz zur Liste werden nicht alle Elemente im Speicher gespeichert, sondern das nächste Element in der angegebenen Reihenfolge generiert. Das Schreiben ohne Verwendung der Einschlussnotation ist wie folgt, aber es ist problematisch, da Sie nur gehen können, wenn Sie eine Funktion erstellen, die einen Generator einmal generiert.
def gen_func():
for i in range(10):
yield i%5
extension_gen = gen_func()
extension_gen
#>>> <generator object gen_func at 0x7f3000166830>
Sie benötigen die Tupeleinschlussnotation nicht oft, aber wenn Sie sie wirklich benötigen, können Sie sie erstellen, indem Sie die Listeneinschlussnotation an die Tupelfunktion übergeben.
tuple([i for i in range(10)])
#>>> (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
[Zusatz] Ich werde den Inhalt des Kommentars hinzufügen. Sie können es an den Generator übergeben, und der Generator kann die Klammern weglassen, daher denke ich, dass es leicht zu lesen ist. (Es wird wie eine Tapple-Inklusionsnotation geschrieben.)
tuple(i for i in range(10))
#>>> (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
#Abkürzung für Klammern in der folgenden Syntax
tuple((i for i in range(10)))
Karten-, Filter- und Einschlussnotation haben ähnliche Ausgaben und werden häufig verglichen. In Python 2-Serien geben Map und Filter eine Liste zurück, sodass sie der Listeneinschlussnotation entspricht. In der Python 3-Serie werden Map- und Filterobjekte zurückgegeben, sodass sie dem Generator entsprechen.
Umschreiben mit Karte
map(lambda i:i**2,range(1,11))
# python2.Für x
#>>> [1, 4, 9, 16, 25, 36, 49, 64, 100]
# python3.Im Fall von x wird ein Iterator mit dem Namen map object zurückgegeben.
#>>> <map at 0x4570f98>
list(map(lambda i:i**2,range(1,11)))
#>>> [1, 4, 9, 16, 25, 36, 49, 64, 100]
#Wenn es sich um eine Listeneinschlussnotation handelt
[i**2 for i in range(1,11)]
#>>> [1, 4, 9, 16, 25, 36, 49, 64, 100]
Umschreiben mit Filter
filter(lambda i:i%2==1, range(1,11))
# python2.Für x
#>>> [1, 3, 5, 7, 9]
# python3.Für x wird ein Iterator namens Filter Object zurückgegeben
#>>> <filter at 0x4578a20>
list(filter(lambda i:i%2==1, range(1,11)))
#>>> [1, 3, 5, 7, 9]
#Wenn es sich um eine Listeneinschlussnotation handelt
[i for i in range(1,11) if i%2==1]
#>>> [1, 3, 5, 7, 9]
Wenn verschachtelt
map(lambda j:j**2, filter(lambda i:i%2==1, range(1,11)))
# python2.Für x
#>>> [1, 9, 25, 49, 81]
# python3.Im Fall von x wird das Filterobjekt zurückgegeben
#>>> <filter at 0x4578a20>
list(map(lambda j:j**2, filter(lambda i:i%2==1, range(1,11))))
#>>> [1, 9, 25, 49, 81]
#Wenn es sich um eine Listeneinschlussnotation handelt
[i**2 for i in range(1,11) if i%2==1]
#>>> [1, 9, 25, 49, 81]
Ich finde es einfacher, die Listeneinschlussnotation zu lesen, aber ist es eine Frage der Vertrautheit? Außerdem ist die Aufnahme von Listen im Allgemeinen schneller.
** Nach dem Lesen dieses Abschnitts empfehlen wir Ihnen, den lesbaren Code zu lesen, um Ihren Geist zu reinigen. ** **. Ich halte es für pythonisch, keine andere mehrstufige oder bedingte Verzweigung als die grundlegende Einschlussnotation zu verwenden.
Verbinden Sie mehrere bedingte Operatoren Am Beispiel von Fizzbuzz sieht es so aus.
fizzbuzz=[]
for i in range(1,16):
if i%15==0:
fizzbuzz.append("fizzbuzz")
elif i%3==0:
fizzbuzz.append("fizz")
elif i%5==0:
fizzbuzz.append("buzz")
else:
fizzbuzz.append(i)
#>>> [1, 2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz']
["fizzbuzz" if i%15==0 else "fizz" if i%3==0 else "buzz"
if i%5==0 else i for i in range(1,16)]
#>>> [1, 2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz']
Ich denke, es gibt einige Fälle, in denen Sie ein Array verschachteln möchten. Sie können dies tun, indem Sie die Listeneinschlussnotation in die Listeneinschlussnotation verschachteln.
outer_list=[]
for i in range(3):
innter_list=[]
for j in range(10):
innter_list.append(j)
outer_list.append(innter_list)
outer_list
#>>> [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
#>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
#>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]
#Wenn Sie in Listeneinschlussnotation schreiben
[[j for j in range(10)] for i in range(3)]
#>>> [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
#>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
#>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]
Wenn es um Tripel geht, wird es schwierig zu lesen, obwohl es Python ist.
Nehmen Sie als Beispiel Flatten. Es ist nicht so schwer zu lesen, wenn man es einmal verstanden hat. Auf den ersten Blick ist die Lesbarkeit deutlich eingeschränkt.
init=[[1,2,3],[4,5],[6,7]]
flatten=[]
for outer in init:
for inner in outer:
flatten.append(inner)
flatten
#>>> [1, 2, 3, 4, 5, 6, 7]
#Entspricht diesem
[inner for outer in init for inner in outer]
#>>> [1, 2, 3, 4, 5, 6, 7]
Lesen Sie im Grunde genommen in der Reihenfolge der for-Klausel auf der linken Seite, und das Letzte, was Sie in die Liste aufnehmen müssen, fällt Ihnen ein. Wenn Sie einrücken möchten, sieht es so aus.
[
inner
for outer in init
for inner in outer
]
#>>> [1, 2, 3, 4, 5, 6, 7]
[Einschließlich if (postfix if) Abschnitt](http://qiita.com/y__sama/items/a2c458de97c4aa5a98e7#if%E3%82%92%E5%90%AB%E3%82%80% Ähnlich wie bei E5% A0% B4% E5% 90% 88% E5% BE% 8C% E7% BD% AEif) verhält es sich so, als würde der Doppelpunkt und der Einzug für jede for-Klausel weggelassen.
Durch die Kombination von Reißverschluss und Doppelschlaufe können Sie Patatoku Cassie mit einem Liner erzeugen.
patato=[]
for i in zip("Pat Auto","Taxi"):
for j in i:
patato.append("".join(j))
"".join(patato)
#>>> 'Patatoku Kashii'
#Wenn Sie in der Einschlussnotation schreiben
"".join(["".join(j) for i in zip("Pat Auto","Taxi") for j in i])
#>>> 'Patatoku Kashii'
#Wenn eingerückt
"".join(
[
"".join(j)
for i in zip("Pat Auto","Taxi")
for j in i
]
)
#>>> 'Patatoku Kashii'
Sie können auch drucken.
[print(k) for i in zip("Pat Auto","Taxi") for j in i for k in j]
#>Pa
#>Ta
#>Zu
#>Ku
#>Leistung
#>Shi
#>- -
#>- -
#>>> [None, None, None, None, None, None, None, None]
#Es gibt keinen Rückgabewert für die Druckfunktion, daher handelt es sich um eine Auswahl von None.
Es ist sehr gut. Wenn Sie mehrere Arrays oder Lambda hinzufügen, ist es schön zu lesen.
import re
DIO=["U","Nutzlos","RR","Arm","Y"]
rslt=[]
for i in DIO:
if re.match("[URY]+",i):
for j in i:
rslt.append(j*2)
"".join(rslt)
#>>> 'UURRRRYY'
#Einschlussnotation
"".join([j*3 for i in DIO if re.match("[URY]+",i) for j in i])
#>>> 'UUURRRRRRYYY'
#Wenn eingerückt, sieht es so aus
"".join(
[
j*4
for i in DIO
if re.match("[URY]+",i)
for j in i
]
)
#>>> 'UUUURRRRRRRRYYYY'
Recommended Posts