Так как вам все равно нужно разобрать его, проще использовать синтаксический анализ в качестве проверки. Многие библиотеки Python также используют этот подход, например, JSON. Это позволяет избежать дублирования логики (1. проверка, 2. разбор), допускает более выразительные сообщения об ошибках и часто намного проще.
Чтобы проанализировать один литерал, такой как 4
или 1 - 3
, разделите его и преобразуйте значения начала / остановки. Это автоматически вызывает ValueError
, если числа не являются действительными целыми числами.
def page_range(literal):
"""
Convert a single page literal into a sequence of pages
:raises ValueError: if literal does not denote a valid page range
"""
start, sep, stop = literal.partition('-') # '1 -3' => '1 ', '-', '3'; ' 4' => ' 4', '', ''
if not start: # may want to raise an error for empty page literals
return []
if not sep: # no '-' in literal, just the start
return [int(start)]
# sep is present, literal is a range of pages
return list(range(int(start), int(stop) + 1))
Вы можете использовать это для объединения страниц из нескольких литералов, таких как 4, 1-3
. Используя исключения, вы можете вызвать ошибку для части недопустимого литерала:
def pages(literals):
for literal in literals.split(','):
try:
yield page_range(literal.strip())
except ValueError: # parsing failed, raise manually to add details
raise ValueError('Invalid page range: %r' % literal)