Überprüfen Sie, ob die Zeichenfolge mit einer der Zeichenfolgen aus einer Liste endet


220

Wie schreibt man den folgenden Code pythonisch?

extensions = ['.mp3','.avi']
file_name = 'test.mp3'

for extension in extensions:
    if file_name.endswith(extension):
        #do stuff

Ich habe eine vage Erinnerung daran, dass die explizite Deklaration der forSchleife vermieden und in die ifBedingung geschrieben werden kann. Ist das wahr?


2
Obwohl diese Frage gut beantwortet ist, hat der Autor vielleicht ursprünglich daran gedacht if any((file_name.endswith(ext) for ext in extensions)).
Sapht

Antworten:


450

Obwohl nicht allgemein bekannt, akzeptiert str.endswith auch ein Tupel. Sie müssen nicht schleifen.

>>> 'test.mp3'.endswith(('.mp3', '.avi'))
True

10
Weißt du, warum es keine Liste akzeptiert, aber ein Tupel? nur neugierig
ilyail3

2
@falsetru Der Link in der Antwort beantwortet diese Frage nicht explizit. Es wird nur erwähnt, dass es Tupel akzeptieren kann , aber nicht, warum es keine Listen akzeptieren kann. Da es sich um beide Sequenzen handelt, besteht der einzige Unterschied, den ich möglicherweise sehen kann, darin, dass Listen veränderlich sind, während Tupel unveränderlich sind. Ich kann mich irren, aber ich kann keinen anderen Grund erkennen, warum dies ausdrücklich angegeben wird.
KymikoLoco

4
Wenn Sie überprüfen möchten, ob eine Zeichenfolge mit einem Buchstaben endet:import string; str.endswith(tuple(string.ascii_lowercase))
Alex Willison

3
Nur eine Anmerkung, endswithakzeptiert Tupel nur für Python 2.5 und höher
Akash Singh

1
Ich wusste das nie! Das ist perfekt!
narr4jesus


6

Nehmen Sie eine Erweiterung aus der Datei und prüfen Sie, ob sie in den Erweiterungen enthalten ist:

>>> import os
>>> extensions = set(['.mp3','.avi'])
>>> file_name = 'test.mp3'
>>> extension = os.path.splitext(file_name)[1]
>>> extension in extensions
True

Verwenden eines Satzes, da die zeitliche Komplexität für die Suche in Sätzen O (1) ( docs ) beträgt .


8
Nur um zu erwähnen, wie Sie die Effizienz erwähnen, ist das .endswith()mit einem internierten Tupel für relativ kurze Tupel schneller als eine festgelegte Suche
Jon Clements

@ JonClements Ich denke, Sie brauchen ein spezielles SO Gold-Kommentar-Abzeichen, um tolle Notizen zu Antworten und Fragen zu machen :)
Alecxe

Nein - ich gehe nur für das "Stalking Alecxe" Abzeichen;)
Jon Clements

2
Beachten Sie auch, dass Sie in Version 2.7 und neuer die mathematische Syntax für Mengen verwenden können {'.mp3','.avi'}, die zusätzliche Typkonvertierung vermeidet und je nach Hintergrund möglicherweise besser lesbar ist ('Obwohl dies zu Verwechslungen mit Wörterbüchern führen kann und nicht zum Erstellen von leeren verwendet werden kann Sätze).
Perkins

@ JonClements eines Tages werde ich so weise wie du :)
Alecxe

3

Es gibt zwei Möglichkeiten: reguläre Ausdrücke und String (str) -Methoden.

String-Methoden sind normalerweise schneller (~ 2x).

import re, timeit
p = re.compile('.*(.mp3|.avi)$', re.IGNORECASE)
file_name = 'test.mp3'
print(bool(t.match(file_name))
%timeit bool(t.match(file_name)

792 ns ± 1,83 ns pro Schleife (Mittelwert ± Standardabweichung von 7 Läufen, jeweils 1000000 Schleifen)

file_name = 'test.mp3'
extensions = ('.mp3','.avi')
print(file_name.lower().endswith(extensions))
%timeit file_name.lower().endswith(extensions)

274 ns ± 4,22 ns pro Schleife (Mittelwert ± Standardabweichung von 7 Läufen, jeweils 1000000 Schleifen)


1

Ich habe das:

def has_extension(filename, extension):

    ext = "." + extension
    if filename.endswith(ext):
        return True
    else:
        return False

1
Du meinst return filename.endswith(ext)? : P
Mr_and_Mrs_D

1

Ich bin gerade darauf gestoßen, als ich nach etwas anderem gesucht habe.

Ich würde empfehlen, mit den Methoden im osPaket zu gehen . Dies liegt daran, dass Sie es allgemeiner gestalten können, um jeden seltsamen Fall zu kompensieren.

Sie können so etwas tun wie:

import os

the_file = 'aaaa/bbbb/ccc.ddd'

extensions_list = ['ddd', 'eee', 'fff']

if os.path.splitext(the_file)[-1] in extensions_list:
    # Do your thing.

0

Eine andere Möglichkeit könnte darin bestehen, die IN-Anweisung zu verwenden:

extensions = ['.mp3','.avi']
file_name  = 'test.mp3'
if "." in file_name and file_name[file_name.rindex("."):] in extensions:
    print(True)

@ Rainald62, indexsollte rindexin diesem Fall sein.
NeverHopeless

0

Eine andere Möglichkeit, die Liste der übereinstimmenden Zeichenfolgen zurückzugeben, ist

sample = "alexis has the control"
matched_strings = filter(sample.endswith, ["trol", "ol", "troll"])
print matched_strings
['trol', 'ol']
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.