检查字符串是否以列表中的某个字符串结尾

311

以下代码如何用Pythonic的方式编写?

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

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

我记得好像可以避免明确声明 for 循环并将其写在 if 条件中。这是真的吗?


5
虽然这个问题已经得到了很好的回答,但也许原作者最初想到的是 if any((file_name.endswith(ext) for ext in extensions)) - sapht
7个回答

634

虽然不是众所周知,str.endswith 也接受元组作为参数。你不需要循环。

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

12
你知道为什么它不接受列表而接受元组吗?只是好奇。 - ilyail3
2
@falsetru 答案中的链接并没有明确回答那个问题。它只是提到它可以接受元组,但没有解释为什么不能接受列表。由于它们都是序列,我唯一可能看到的区别是列表是可变的,而元组是不可变的。我可能错了,但我没有看到任何其他明确说明的原因。 - KymikoLoco
6
如果您想检查一个字符串是否以字母结尾:import string; str.endswith(tuple(string.ascii_lowercase)) - Alex Willison
3
注意:endswith 函数只接受元组作为参数,适用于 Python 2.5 及以上版本。 - Akash Singh
2
@ilyail3:我怀疑目标是推动人们使用高效的结构。99%的情况下,要测试的后缀都是常量字符串字面值。如果将它们放在一个“list”中,CPython优化器(不知道“endswith”不会存储/改变它们)必须在每次调用时重新构建“list”。将它们放在一个“tuple”中,优化器可以在编译时存储“tuple”,并且只需从常量数组中廉价地加载它们。类似于在字符串可迭代对象上使用“sum”的提示;两种方式都可以工作,但是错误的方式代码会更慢。 - ShadowRanger
@falsetru 我的错,删除它以避免混淆。 - Atlantis

63

只需使用:

if file_name.endswith(tuple(extensions)):

简单而有效! - Ced

8
另一种返回匹配字符串列表的方法是:
sample = "alexis has the control"
matched_strings = filter(sample.endswith, ["trol", "ol", "troll"])
print matched_strings
['trol', 'ol']

在Python>3.8中应该这样写:print(list(matched_strings))。 - parvaneh shayegh

6

有两种方法:正则表达式和字符串(str)方法。

字符串方法通常更快(~2倍)。

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纳秒,标准差为1.83纳秒(在7组,每组1000000次循环的情况下)。

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

每个循环的平均时间为274纳秒±4.22纳秒(7次运行的平均值和标准偏差,共1000000次循环)


2

我在寻找其它东西时无意中发现了这个。

我建议使用os包中的方法。这是因为您可以使其更加通用,以弥补任何奇怪的情况。

您可以这样做:

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.

1
我有这个:

我有这个:

def has_extension(filename, extension):

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

3
你的意思是 return filename.endswith(ext) 吗? :P - Mr_and_Mrs_D

0

另一种可能性是利用IN语句:

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

@Rainald62,在那种情况下,index 应该改为 rindex - NeverHopeless

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接