Шаг 24.
Python: сборник рецептов.
Строки и текст. Поиск текста в начале и в конце строки

    На этом шаге мы рассмотрим использование методов startswith() и endswith().

Задача

    Вам нужно проверить начало или конец строки на присутствие неких текстовых шаблонов, таких как расширения файлов, схемы URL и т. д.

Решение

    Простой способ проверить начало или конец строки - применить метод str.startswith() или str.endswith(). Например:

>>> filename = 'spam.txt'
>>> filename.endswith('.txt')
True
>>> filename.startswith('file:')
False
>>> url = 'http://www.python.org'
>>> url.startswith('http:')
True
>>>

    Если вам нужно проверить несколько вариантов, передайте кортеж с ними в startswith() или endswith():

>>> import os
>>> filenames = os.listdir('.')
>>> filenames
[ 'Makefile', 'foo.c', 'bar.py', 'spam.c', 'spam.h']
>>> [name for name in filenames if name.endswith(('.c', '.h')) ]
['foo.c', 'spam.c', 'spam.h']
>>> any(name.endswith('.py') for name in filenames)
True
>>>

    А вот другой пример:

from urllib.request import urlopen

def read_data(name):
    if name.startswith(('http:', 'https:', 'ftp:')): 
        return urlopen(name).read() 
    else:
        with open(name) as f: 
            return f.read()

    Любопытно, что в этом случае на вход нужно подавать именно кортеж. Если так случилось, что варианты выбора собраны у вас в списке или множестве, сначала сконвертируйте их с помощью tuple(). Например:

>>> choices = ['http:', 'ftp:']
>>> url = 'http://www.python.org'
>>> url.startswith(choices)
Traceback (most recent call last):
.   .   .   .
TypeError: startswith first arg must be str or a tuple of str, not list
>>> url.startswith(tuple(choices))
True
>>> 

Обсуждение

    Методы startswith() и endswith() предоставляют весьма удобный способ проверки префиксов и окончаний. Такие же операции можно осуществить с помощью срезов, но это намного менее элегантно. Например:

>>> filename = 'spam.txt'
>>> filename[-4:] == '.txt'
True
>>> url = 'http://www.python.org'
>>> url[:5] == 'http:' or url[:6] == 'https:' or url[:4] == 'ftp:'
True
>>>

    Вы также можете склониться к использованию регулярных выражений в качестве альтернативы. Например:

>>> import re
>>> url = 'http://www.python.org'
>>> re.match('http:|https:|ftp:', url)
<re.Match object; span=(0, 5), match='http:'>
>>> 

    Такой подход работает, но часто это будет огнем из пушки по воробьям. Использование вышеописанного рецепта проще и работает быстрее.

    И последнее: методы startswith() и endswith() отлично работают вместе с другими операциями, такими как обычные методы свертки данных. Например, это выражение проверяет каталог на присутствие файлов определенных типов:

if any(name.endswith(('.c', '.h')) 
    for name in listdir(dirname)):
        .   .   .   .

    На следующем шаге мы рассмотрим поиск строк с использованием масок оболочки.




Предыдущий шаг Содержание Следующий шаг