Простой Python — страница 61 из 66

10. Найдите все слова, которые заканчиваются на букву «r».

Это упражнение с подвохом. Мы получаем правильный результат для слов, которые заканчиваются на «r»:

>>> pat = r'\b\w*r\b'

>>> re.findall(pat,mammoth)

['your', 'fair', 'Or', 'scar', 'Mr', 'far', 'For', 'your', 'or']

Однако результаты будут не так хороши, если мы поищем слова, которые заканчиваются на «l»:

>>> pat = r'\b\w*l\b'

>>> re.findall(pat,mammoth)

['All', 'll', 'Provincial', 'fall']

Что здесь делает буквосочетание «ll»? Паттерн \w совпадает только c буквами, цифрами и подчеркиваниями, но не с апострофами ASCII. В результате вы увидите буквосочетание «ll». Мы можем обработать этот крайний случай, добавив апостроф в список символов, с которыми должен совпасть набор символов. Наша первая попытка не работает:

>>>>>> pat = r'\b[\w']*l\b'

··File "", line 1

····pat = r'\b[\w']*l\b'

Python указывает на окрестности ошибки, но может потребоваться какое-то время, чтобы увидеть: ошибка заключалась в том, что строка шаблона окружена такими же апострофами — символами кавычки. Один из способов решить эту проблему — использовать управляющую последовательность с обратным слешем:

>>> pat = r'\b[\w\']*l\b'

>>> re.findall(pat, mammoth)

['All', "you'll", 'Provincial', 'fall']

Еще одно решение — окружить строку шаблона двойными кавычками:

>>> pat = r"\b[\w']*l\b"

>>> re.findall(pat, mammoth)

['All', "you'll", 'Provincial', 'fall']

11. Найдите все слова, которые содержат три гласные подряд.

Начиная с границы слова, любое число символов слова, три гласные и далее любые символы, не являющиеся гласными, до конца слова:

>>> pat = r'\b\w*[aeiou]{3}[^aeiou]\w*\b'

>>> re.findall(pat, mammoth)

['queen', 'quietly', 'beau\nIn', 'queen', 'squeeze', 'queen']

Выглядит правильно, за исключением строки 'beau\nIn'. Мы искали строку mammoth целиком. Конструкция [^aeiou] совпадает с любыми символами, не являющимися гласными, включая \n (перенос строки, который отмечает конец текстовой строки). Нам нужно добавить еще кое-что в набор игнорируемых символов: \s совпадает с любыми символами пробелов, включая \n:

>>> pat = r'\b\w*[aeiou]{3}[^aeiou\s]\w*\b'

>>> re.findall(pat, mammoth)

['queen', 'quietly', 'queen', 'squeeze', 'queen']

В этот раз мы не нашли слово beau, поэтому нужно внести в шаблон еще одно исправление: совпадение с любым числом (даже нулем) не гласных после трех гласных. Наш предыдущий шаблон всегда совпадал с одним не гласным символом:

>>> pat = r'\b\w*[aeiou]{3}[^aeiou\s]*\w*\b'

>>> re.findall(pat, mammoth)

['queen', 'quietly', 'beau', 'queen', 'squeeze', 'queen']

Что это показывает? Среди всего прочего, что регулярные выражения могут сделать многое, но их может быть очень трудно написать правильно.

12. Используйте метод unhexlify для того, чтобы преобразовать эту шестнадцатеричную строку (созданную путем объединения двух строк, что позволило ей разместиться на странице) в переменную типа bytes с именем gif:

'47494638396101000100800000000000ffffff21f9' +

'0401000000002c000000000100010000020144003b'

>>> import binascii

>>> hex_str = '47494638396101000100800000000000ffffff21f9' + \

…·····'0401000000002c000000000100010000020144003b'

>>> gif = binascii.unhexlify(hex_str)

>>> len(gif)

42

13. Байты, содержащиеся в переменной gif, определяют однопиксельный прозрачный GIF-файл. Этот формат является одним из самых распространенных. Корректный файл формата GIF начинается со строки GIF89a. Является ли этот файл корректным?

>>> gif[:6] == b'GIF89a'

True

Обратите внимание на то, что нам нужно использовать b, чтобы указать, что строка состоит из байтов, а не из символов Unicode. Вы можете сравнить байты с байтами, но не можете сравнивать байты и символы:

>>> gif[:6] == 'GIF89a'

False

>>> type(gif)

>>> type('GIF89a')

>>> type(b'GIF89a')

14. Ширина файла формата GIF является шестнадцатибитным целым числом с обратным порядком байтов, которое начинается со смещения 6 байт. Его высота имеет такой же размер и начинается со смещения 8 байт. Извлеките и выведите на экран эти значения для переменной gif. Равны ли они 1?

>>> import struct

>>> width, height = struct.unpack('

>>> width, height

(1, 1)

Глава 8. Данные должны куда-то попадать

1. Присвойте строку 'This is a test of the emergency text system' переменной test1 и запишите переменную test1 в файл с именем test.txt:

>>> test1 = 'This is a test of the emergency text system'

>>> len(test1)

43

Вот как можно сделать это с помощью функций open, write и close:

>>> outfile = open('test.txt', 'wt')

>>> outfile.write(test1)

43

>>> outfile.close()

Или можете использовать with и избежать вызова close (Python сделает это за вас):

>>> with open('test.txt', 'wt') as outfile:

…·····outfile.write(test1)

43

2. Откройте файл test.txt и считайте его содержимое в строку test2. Совпадают ли строки test1 и test2?

>>> with open('test.txt', 'rt') as infile:

…·····test2 = infile.read()

>>> len(test2)

43

>>> test1 == test2

True

3. Сохраните следующие несколько строк в файл books.csv. Обратите внимание на то, что, если поля разделены запятыми, вам нужно заключить поле в кавычки, если оно содержит запятую:

author,book

J R R Tolkien,The Hobbit

Lynne Truss,"Eats, Shoots & Leaves"

>>> text = '''author,book

… J R R Tolkien,The Hobbit

… Lynne Truss,"Eats, Shoots & Leaves"

… '''

>>> with open('test.csv', 'wt') as outfile:

…·····outfile.write(text)

73

4. Используйте модуль csv и его метод DictReader, чтобы считать содержимое файла books.csv в переменную books. Выведите на экран значения переменной books. Обработал ли метод DictReader кавычки и запятые в заголовке второй книги?

>>> with open('test.csv', 'rt') as infile:

…·····books = csv.DictReader(infile)

…·····for book in books:

…·········print(book)

{'book': 'The Hobbit', 'author': 'J R R Tolkien'}

{'book': 'Eats, Shoots & Leaves', 'author': 'Lynne Truss'}

5. Создайте CSV-файл с именем books.csv и запишите его в следующие строки:

title,author,year

The Weirdstone of Brisingamen,Alan Garner,1960

Perdido Street Station,China Miéville,2000

Thud!Terry Pratchett,2005

The Spellman Files,Lisa Lutz,2007