Математический практикум по Питону.
Вводится базовы объекты из Питона (Python): кортеж (touple) и словарь (dict). Ключевые слова: touple, index, count, zip, list, dict, pop, popitem, update, setdefault, keys, items, values.
Это предварительная версия! Любые замечания приветствуются.
Мы уже ранее его видели. Всякий раз когда выводятся числа в круглых скобках -- это он. Схож со список, но имет свои отличия. Скорее такой тип данных следует считать набором, т.е. фиксированного размера объект. кортеж.
a = 3
b = 5
a, b
(3, 5)
Создание
a = (0, 4) # Создаем кортеж в явном виде.
a
(0, 4)
len(a) # Как и у списка -- его длина, т.е. количество элементов в кортеже.
2
создания кортежа из одного элемента вещь хитрая.
(7)
7
('один элемент') # Это просто строка.
'один элемент'
# Нужно так:
('один элемент',) # В конце запятая.
('один элемент',)
Предполагается, что компоненты будут иметь определеный смысл.
# Можно задать некую структурированную иформацию.
фио = ('Ломоносов', 'Михаил', 'Васильевич')
фио # Фамилия, имя, отчество.
('Ломоносов', 'Михаил', 'Васильевич')
# Можно индексировать. Причем под заданным индексом
фио[1] # будет информация определенного типа.
# В данном случае, имя.
'Михаил'
# Можно задать и другие данные.
года = (1711, 1765) # Например, период лет: начало и конец.
person = ( фио, года) # Потом объеденить.
# Можно все задать одним больших выражением.
person2 = ( ('Ги́льберт', 'Дави́д', 'Отто'), (1862, 1943) )
# Смысл кортежа в том, что объекты под фиксированным индексом имеют одинаковую интерпритацию.
print( person[0][1], person[0][0], 'родился в', person[1][0], 'г.')
print( person2[0][1], person2[0][0], 'родился в', person2[1][0], 'г.')
Михаил Ломоносов родился в 1711 г. Дави́д Ги́льберт родился в 1862 г.
# можно писать общий код:
prnt_bio = lambda pers: print( pers[0][1], pers[0][0], 'родился в', pers[1][0], 'г.')
prnt_bio(person) # Вызов для одного,
prnt_bio(person2) # вызов для другого.
Михаил Ломоносов родился в 1711 г. Дави́д Ги́льберт родился в 1862 г.
nums = (2, 1, 3, 1, 5, 6)
# Как и в списке подсчитывает количество элементов равных данному.
nums.count(1)
2
# Аналогично списку. Поиск элемента равному даному.
nums.index(1) # Возвращает индекс первого вхождения.
1
# Указав во втором аргументе с кого индекса начинать
nums.index(1, 2) # можно найти второе входение.
3
# Проверяет принадлежность элемента списку.
4 in nums, 3 in nums
(False, True)
Сложный индекс
nums[2:6]
(3, 1, 5, 6)
Остались только фамилия и отчество.
фио[::2]
('Ломоносов', 'Васильевич')
фио[0]
'Ломоносов'
# Кортеж постоянен, т.е. неизменяемый.
фио[1] = 'Максим' # Поэтому, присваивать новое значение нельзя.
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-22-ce03378bb415> in <module> 1 # Кортеж постоянен, т.е. неизменяемый. ----> 2 фио[1] = 'Максим' # Поэтому, присваивать новое значение нельзя. TypeError: 'tuple' object does not support item assignment
Как и менять состав нельзя:
# Пытаемся по аналогии со список добавить элемент.
nums.append(8)
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-23-bb909b1bba77> in <module> 1 # Пытаемся по аналогии со список добавить элемент. ----> 2 nums.append(8) AttributeError: 'tuple' object has no attribute 'append'
del nums[1] # Удалить поле нельзя.
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-24-6731ca5f41f9> in <module> ----> 1 del nums[1] # Удалить поле нельзя. TypeError: 'tuple' object doesn't support item deletion
Добавить новое поле
# Попробуем путем добавления списка.
person + ['деревня Мишанинская'] # К кортежу список добавить нельзя.
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-25-3b398c417e9f> in <module> 1 # Попробуем путем добавления списка. ----> 2 person + ['деревня Мишанинская'] # К кортежу список добавить нельзя. TypeError: can only concatenate tuple (not "list") to tuple
# Поробуем добавить "кортеж".
person + ('деревня Мишанинская')
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-26-c7436a4c1569> in <module> 1 # Поробуем добавить "кортеж". ----> 2 person + ('деревня Мишанинская') TypeError: can only concatenate tuple (not "str") to tuple
('деревня Мишанинская') # Скобки ничего не значят.
# Получится просто строка.
'деревня Мишанинская'
# А теперь уж добавлением кортежа.
person + ('деревня Мишанинская',) # Все дело в запятой.
# А так можно. Мы создали новый набор.
(('Ломоносов', 'Михаил', 'Васильевич'), (1711, 1765), 'деревня Мишанинская')
person # ожидаемо не изменился
(('Ломоносов', 'Михаил', 'Васильевич'), (1711, 1765))
person_ex = person + ('деревня Мишанинская',) # Сохраним в переменную.
person_ex
(('Ломоносов', 'Михаил', 'Васильевич'), (1711, 1765), 'деревня Мишанинская')
# Теперь в поле под индексом 2 город рождения.
person_ex[2]
'деревня Мишанинская'
prnt_bio = lambda pers: print( pers[0][1], pers[0][0], 'родился в', pers[1][0], 'г.', 'в', pers[2])
prnt_bio( person_ex ) # Выведем расширенную информацию.
Михаил Ломоносов родился в 1711 г. в деревня Мишанинская
prnt_bio( person ) # Разумеется не будет работать с кортежом не имеющего данного поля.
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-33-88319524c964> in <module> ----> 1 prnt_bio( person ) # Разумеется не будет работать с кортежом не имеющего данного поля. <ipython-input-32-7b148abd6a55> in <lambda>(pers) ----> 1 prnt_bio = lambda pers: print( pers[0][1], pers[0][0], 'родился в', pers[1][0], 'г.', 'в', pers[2]) 2 prnt_bio( person_ex ) # Выведем расширенную информацию. IndexError: tuple index out of range
фио, года
(('Ломоносов', 'Михаил', 'Васильевич'), (1711, 1765))
фио + года
('Ломоносов', 'Михаил', 'Васильевич', 1711, 1765)
(фио,)+(года,)
(('Ломоносов', 'Михаил', 'Васильевич'), (1711, 1765))
Упр. Список кортежей некой информации: фио, эмитент/цена, нефтяное месторождение/прогнозируемый объем запаса. Функция печати информации. Распечатать информацию элементов списка.
# Создадим два списка.
a = [1, 2, 3]
b = ['a', 'b', 'c']
a, b
([1, 2, 3], ['a', 'b', 'c'])
# Попарно объеденим их соответствующие элементы.
c = zip( a, b ) # Тоже генератор списка.
c
<zip at 0x7f12b4856a88>
# Сшивает два списка.
d = list( c ) # Элементы которого картеж из элементов исходных список.
d
[(1, 'a'), (2, 'b'), (3, 'c')]
d[1] # Кортеж из элементов a[1] и b[1]
(2, 'b')
a[1], b[1]
(2, 'b')
# Можно сшивать больше одного списка.
e = list( zip( [1,2,3], ['a','b','c'],d))
e
[(1, 'a', (1, 'a')), (2, 'b', (2, 'b')), (3, 'c', (3, 'c'))]
# Тоже будет кортежом.
e[1] # Только больше элементов.
(2, 'b', (2, 'b'))
Поэлементное произведение списоков
a
[1, 2, 3]
b = [4,5,6]
c = list( zip(a, b) )
c
[(1, 4), (2, 5), (3, 6)]
# Получаем список произведения двух списков.
list( map( lambda x: x[0] * x[1], c) )
[4, 10, 18]
stud = ['Маша', 'Ката', 'Лена']
k=0
for it in stud:
print( f"студент {it} под №{k}" )
k += 1
студент Маша под №0 студент Ката под №1 студент Лена под №2
enum = enumerate(stud)
enum
<enumerate at 0x7f12b484a708>
next( enum )
(0, 'Маша')
for itt in enumerate(stud):
print( f"студент {itt[1]} под №{itt[0]}" )
студент Маша под №0 студент Ката под №1 студент Лена под №2
Воспользуемся автоматической распаковкой.
for k, it in enumerate(stud):
print( f"студент {it} под №{k}" )
студент Маша под №0 студент Ката под №1 студент Лена под №2
Пример:
по стране --> столица
по слову на русском языке --> слова на английском
Создание
country = dict() # Созданем словарь.
# Определяем элементы.
country['Россия'] = 'Москва'
country['Франция'] = 'Париж'
country['Италия'] = 'Рим'
# Ключь может иметь разную природу.
country[8] = 10 # Дали соответствие числу.
# Просмотр словаря. Он задан фигурными скобками.
country # Ключ и значение указаны через двоеточее.
# Сами сущности перечислены через запятую.
{'Россия': 'Москва', 'Франция': 'Париж', 'Италия': 'Рим', 8: 10}
# Можно и задать словарь таким же способом.
eng2rus = { 'cat':'кошка', 'dog' : 'собака' }
eng2rus
{'cat': 'кошка', 'dog': 'собака'}
empty = {} # можно и пустой словарь задать.
empty
{}
type( country ), type( eng2rus ), type( empty ) # Выведем тип явно.
(dict, dict, dict)
empty = dict() # А теперь можно явно и задать.
empty
{}
Копирование
aa = id( eng2rus )
eng2rus_copy = eng2rus.copy() # Делаем копию по аналогии со списком.
bb = id( eng2rus_copy )
eng2rus_copy, aa == bb # Словарь скопирован, и сам объект новый.
({'cat': 'кошка', 'dog': 'собака'}, False)
eng2rus_copy == eng2rus
True
b = id(eng2rus_copy)
eng2rus_copy.clear() # Очищаем словарь.
a = id(eng2rus_copy)
eng2rus_copy, a == b # Словарь очищен, а объект сохранился.
({}, True)
"Индексация"
или как извлечь значение
# Обобщается понятие индекса. Он тепер нетолько числовой.
country['Франция'] # В квадратных скобках указывется ключ.
'Париж'
'Франция' in country # Проверка нахождения ключа в словаре.
True
# Если ключа нет в словаре, то выдается ошибка.
country['Германия']
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-67-af7696405b79> in <module> 1 # Если ключа нет в словаре, то выдается ошибка. ----> 2 country['Германия'] KeyError: 'Германия'
Можно более безопасно извлекать. Так, чтобы не обрабатывать в яном виде отсутствие ключа.
country.get('Россия', 'информации нет')
'Москва'
# Можно попытатся извлечь и в случае отсутсвия ключа
cap = country.get('Германия', 'информации нет')
cap # вернуть значение по умолчанию.
'информации нет'
# Можно вообще не указать и значения по умолчанию.
cap = country.get('Германия')
cap, type(cap) # Специальное значение и тип.
(None, NoneType)
country # Значение для ключа используемого в get не появилось.
{'Россия': 'Москва', 'Франция': 'Париж', 'Италия': 'Рим', 8: 10}
Так можно
country['Россия']
'Москва'
Так нельзя...
country['Россия':'Италия']
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-73-8503d1f9a859> in <module> ----> 1 country['Россия':'Италия'] TypeError: unhashable type: 'slice'
Как функцию тоже нельзя.
country('Россия')
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-74-e5ddd466f5cb> in <module> ----> 1 country('Россия') TypeError: 'dict' object is not callable
list(map(country, ['Россия']))
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-75-72b86eff958c> in <module> ----> 1 list(map(country, ['Россия'])) TypeError: 'dict' object is not callable
Но так можно
list(map(lambda x:country[x], ['Россия', 'Франция']))
['Москва', 'Париж']
Упр. Посчитать сколько раз встречаются различные буквы в тексте.
# Но значение тем не менее можно задать.
country['Германия'] = 'Берлин'
country # Ранее в словаре его не было. Теперь есть.
{'Россия': 'Москва', 'Франция': 'Париж', 'Италия': 'Рим', 8: 10, 'Германия': 'Берлин'}
# Один словарь обновляет исходный.
country.update({'Россия' : 'Питербург', 'США' : 'Вашингтон'})
country # В исходном обновляются значения (Россия) и добавляются новые (США).
{'Россия': 'Питербург', 'Франция': 'Париж', 'Италия': 'Рим', 8: 10, 'Германия': 'Берлин', 'США': 'Вашингтон'}
Новое значение
# В отличие от get, setdefault присваивает новое зачение,
q = country.setdefault('Канада', 'Оттава') # если его нет в словаре.
q # Как и с get, setdefault возвращает значение даже, если его нет в словаре.
'Оттава'
# Значение (Оттава) для нового ключа (Канада) появилось в словаре.
country
{'Россия': 'Питербург', 'Франция': 'Париж', 'Италия': 'Рим', 8: 10, 'Германия': 'Берлин', 'США': 'Вашингтон', 'Канада': 'Оттава'}
# Но, если в словаре ключ есть, то setdefault, в отличие от присвоения,
cap = country.setdefault('Россия', 'Москва') # старое значение не обновляет.
cap # А также, возвращает текущее значение ключа.
'Питербург'
country # Значение не обновилось.
{'Россия': 'Питербург', 'Франция': 'Париж', 'Италия': 'Рим', 8: 10, 'Германия': 'Берлин', 'США': 'Вашингтон', 'Канада': 'Оттава'}
cap
'Питербург'
country['Россия'] = 'Москва' # а так обновим.
country
{'Россия': 'Москва', 'Франция': 'Париж', 'Италия': 'Рим', 8: 10, 'Германия': 'Берлин', 'США': 'Вашингтон', 'Канада': 'Оттава'}
country_cpy = country.copy()
country.pop()
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-86-e8d15a29d248> in <module> ----> 1 country.pop() TypeError: pop expected at least 1 arguments, got 0
# Можно извлечь конкретный элемент.
country.pop('Франция')
'Париж'
country # Франции больше в словаре нет.
{'Россия': 'Москва', 'Италия': 'Рим', 8: 10, 'Германия': 'Берлин', 'США': 'Вашингтон', 'Канада': 'Оттава'}
# Извлекаем сразу одну сущность (случайно,
elem = country.popitem() # на порядок рассчитывать не стоит).
elem # Кортеж из ключа и значения.
('Канада', 'Оттава')
country
{'Россия': 'Москва', 'Италия': 'Рим', 8: 10, 'Германия': 'Берлин', 'США': 'Вашингтон'}
f'Кортеж состоящий из ключа, {elem[0]}, и значения, {elem[1]}.'
'Кортеж состоящий из ключа, Канада, и значения, Оттава.'
Упр. Составить словарь функций: sin, tan. Условно будет возможным func['sin'](0.5).
Обработка списком
Как обрабатывать элементы словаря. Например, мы хотим найти элемент словаря с определенным свойстом или что-то со всеми ими сделать.
# Преобразование словаря в список.
cc = list( country ) # Останутся только ключи. Значения пропадут.
cc
['Россия', 'Италия', 8, 'Германия', 'США']
list( map( print, cc) ) # Например вывести название стран.
Россия Италия 8 Германия США
[None, None, None, None, None]
del cc[2]
cc
['Россия', 'Италия', 'Германия', 'США']
cc.sort()
cc
['Германия', 'Италия', 'Россия', 'США']
# Последнее эквивалентно явному вызову метода keys.
dd = list(country.keys())
dd # Можно узнать какие ключи есть.
['Россия', 'Италия', 8, 'Германия', 'США']
# Но никто не запрещает "вспомнить" значения.
list( map( lambda x:print('столицей', x, 'является', country[x]), cc) )
# Используем словарь для вывода значений.
столицей Германия является Берлин столицей Италия является Рим столицей Россия является Москва столицей США является Вашингтон
[None, None, None, None]
# А можно и сразу получить доступ к ключю и его значению.
ii = list( country.items() )
ii
[('Россия', 'Москва'), ('Италия', 'Рим'), (8, 10), ('Германия', 'Берлин'), ('США', 'Вашингтон')]
# Тогда можно так.
list( map( lambda x:print('столицей', x[0], 'является', x[1]), ii) )
столицей Россия является Москва столицей Италия является Рим столицей 8 является 10 столицей Германия является Берлин столицей США является Вашингтон
[None, None, None, None, None]
country.values() # Данный метод наоборот возвращает значения.
dict_values(['Москва', 'Рим', 10, 'Берлин', 'Вашингтон'])
stud = dict({'Максим' : 'Россия', 'Аннетт' : 'Франция', 'Дима' : 'Россия', 'Луиза' : 'Франция'})
stud # Словарь оторажает имя на страну из которой приехал студент.
{'Максим': 'Россия', 'Аннетт': 'Франция', 'Дима': 'Россия', 'Луиза': 'Франция'}
zz = stud.values() # Страны из которых приехали студенты.
zz
dict_values(['Россия', 'Франция', 'Россия', 'Франция'])
countries = list(stud.values())
countries # Список стран.
['Россия', 'Франция', 'Россия', 'Франция']
# Благодаря славарю получили список стран без повторов.
qq = dict.fromkeys(countries) # Хак..
qq
{'Россия': None, 'Франция': None}
list(qq.keys())
['Россия', 'Франция']
#zz.sort
словарь в обратную сторону
ii
[('Россия', 'Москва'), ('Италия', 'Рим'), (8, 10), ('Германия', 'Берлин'), ('США', 'Вашингтон')]
Построим словарь в обратную сторону.
rr=dict()
# Попробуем так.
list(map( lambda i: rr[i[1]] = rr[i[0]], ii))
# Но будет ошибка.
File "<ipython-input-111-04ed97b43377>", line 2 list(map( lambda i: rr[i[1]] = rr[i[0]], ii)) ^ SyntaxError: lambda cannot contain assignment
Нельзя присваивать в ламбда операторе. Предполагается, что ламбда оператор действует как функция: на вход значение, на выход значение. Ничего присваивать нельзя.
если нельзя, но очень хочется, то можно
# Вызовем метод словаря. setdefault позволяет менять значение.
list(map( lambda i: rr.setdefault(i[1],i[0]), ii))
# Ошибки не будет.
['Россия', 'Италия', 8, 'Германия', 'США']
rr
{'Москва': 'Россия', 'Рим': 'Италия', 10: 8, 'Берлин': 'Германия', 'Вашингтон': 'США'}
Сложный ключ
Наборы могут выступать в качестве ключа/индекса у словаря.
name = ['Ломоносов', 'Михаил', 'Васильевич']
name
['Ломоносов', 'Михаил', 'Васильевич']
advisor = ['Вольф', 'Христиан фон', '?']
advisor
['Вольф', 'Христиан фон', '?']
# Хотим создать словарь в котором по ключу можно узнать научного руководителя.
advisors = dict()
advisors[name] = advisor # Система выдаст ошибку.
# По сути по причине того, что список мы знаем как изменяемый объект.
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-117-93a3595a87e6> in <module> ----> 1 advisors[name] = advisor # Система выдаст ошибку. 2 # По сути по причине того, что список мы знаем как изменяемый объект. TypeError: unhashable type: 'list'
name = ('Ломоносов', 'Михаил', 'Васильевич')
advisor = ('Вольф', 'Христиан фон', '?')
name, advisor
(('Ломоносов', 'Михаил', 'Васильевич'), ('Вольф', 'Христиан фон', '?'))
# Теперь разрешено добавить запись в словарь.
advisors[name] = advisor
advisors # Видим что изменение что надо.
{('Ломоносов', 'Михаил', 'Васильевич'): ('Вольф', 'Христиан фон', '?')}
f'Научным руководителем {name} является {advisors[name]}.'
"Научным руководителем ('Ломоносов', 'Михаил', 'Васильевич') является ('Вольф', 'Христиан фон', '?')."
advisors[name]
('Вольф', 'Христиан фон', '?')
import re
Поиск чисел
Что если нужно найти числа? Целые числа. Что есть корректно записанное целое число? Это символ из 1 до 9, а далее символы 0-9 в любом количестве.
s = 'некий 1234.. еще немного 567... ошибка 045..и вот завершающий 89'
for match in re.finditer('[1-9]+[0-9]*', s):
print( s[match.start():match.end()] )
1234 567 45 89
Но сработает так
s = 'ошибка 045..'
match = re.search('[1-9]+[0-9]*', s)
s[match.start():match.end()]
'45'
Нужно указать что перед найденной строкой не было цифр... Для этого есть мета символ ^
s = 'ошибка 045.. 35лл'
match = re.search('[\s][1-9]+[0-9]*', s)
s[match.start():match.end()]
' 35'
s = 'ошибка 045..35лл'
match = re.search('[^0-9][1-9]+[0-9]*', s)
s[match.start():match.end()]
'.35'
Ответ можно сгруппировать
s = 'ошибка 045..35лл'
match = re.search('[^0-9]([1-9]+[0-9]*)', s)
s[match.start():match.end()]
'.35'
match.groups(1)
('35',)
s = "Вермя 10:23:45 текст"
match = re.search('[0-9][0-9]:[0-9][0-9]:[0-9][0-9]', s)
s[match.start():match.end()]
'10:23:45'
Время найдено, но его все-равно нужно парзисть.
match = re.search('([0-9][0-9]):([0-9][0-9]):([0-9][0-9])', s)
s[match.start():match.end()]
'10:23:45'
Но, теперь вырезаны отдельные найденные части.
match.groups()
('10', '23', '45')
match.group()
'10:23:45'
match.group(1)
# Вывела часы.
'10'
hours = match.group(1)
mins = match.group(2)
secs = match.group(3)
hours, mins, secs
('10', '23', '45')
# Очень важно указать r!
re.sub( '([0-9][0-9]):([0-9][0-9]):([0-9][0-9])', r'\1 часов и \2 минут', s)
# \1 \2 указывают на номер группы
'Вермя 10 часов и 23 минут текст'
match = re.search('(?P<часы>[0-9][0-9]):(?P<минуты>[0-9][0-9]):(?P<секунды>[0-9][0-9])', s)
s[match.start():match.end()]
'10:23:45'
Теперь можно и так:
match.groupdict()
{'часы': '10', 'минуты': '23', 'секунды': '45'}
match.group('часы')
'10'
# Очень важно указать r!
re.sub( '(?P<часы>[0-9][0-9]):(?P<минуты>[0-9][0-9]):(?P<секунды>[0-9][0-9])', r'\g<часы> часов и \g<минуты> минут', s)
# \1 \2 указывают на номер группы
'Вермя 10 часов и 23 минут текст'
Когда их много
s
'Вермя 10:23:45 текст'
rtime = '(?P<часы>[0-9][0-9]):(?P<минуты>[0-9][0-9]):(?P<секунды>[0-9][0-9])'
re.findall( rtime, 'd' +s+'ab')
[('10', '23', '45')]
'(?P<часы>[0-9][0-9]):(?P<минуты>[0-9][0-9]):(?P<секунды>[0-9][0-9])|(?P<words>[abcd]+)'
'(?P<часы>[0-9][0-9]):(?P<минуты>[0-9][0-9]):(?P<секунды>[0-9][0-9])|(?P<words>[abcd]+)'
re.findall(rtime+'|(?P<words>[abcd]+)', 'd' +s+'ab')
[('', '', '', 'd'), ('10', '23', '45', ''), ('', '', '', 'ab')]
re.findall("a*","abcdabfga")
['a', '', '', '', 'a', '', '', '', 'a', '']
rall = rtime+'|(?P<words>[abcd]+)'
rall
'(?P<часы>[0-9][0-9]):(?P<минуты>[0-9][0-9]):(?P<секунды>[0-9][0-9])|(?P<words>[abcd]+)'
Упр. Как извлечь название групп? Должно получится ['часы', 'минуты', 'секунды', 'words']
s = 'некий 1234.. еще немного 567... ошибка 045..и вот завершающий 89'
ss = s
match = re.search('[^0-9][1-9]+[0-9]*', ss)
res = []
src = []
while match != None:
src = src + [ss[:match.start()]] + [ss[match.start():match.end()]]
res = res + [ss[:match.start()]] + ['<NUM>']
ss = ss[match.end():]
match = re.search('[^0-9][1-9]+[0-9]*', ss )
print(res)
print(src)
['некий', '<NUM>', '.. еще немного', '<NUM>', '... ошибка 045..и вот завершающий', '<NUM>'] ['некий', ' 1234', '.. еще немного', ' 567', '... ошибка 045..и вот завершающий', ' 89']
s = '1234.. еще немного 567... ошибка 045..и вот завершающий 89'
ss = s
reg = '([^0-9][1-9]+[0-9]*)|(^[1-9]+[0-9]*)'
match = re.search( reg, ss)#! тут |[0-9]*
res = []
src = []
while match != None:
src = src + [ss[:match.start()]] + [ss[match.start():match.end()]]
res = res + [ss[:match.start()]] + ['<NUM>']
ss = ss[match.end():]
match = re.search('[^0-9][1-9]+', ss )#[0-9]*
print(res)
print(src)
['', '<NUM>', '.. еще немного', '<NUM>', '... ошибка 045..и вот завершающий', '<NUM>'] ['', '1234', '.. еще немного', ' 567', '... ошибка 045..и вот завершающий', ' 89']
res = []
src = []
last = 0
for match in re.finditer( reg, s):
src = src + [s[last:match.start()]] + [s[match.start():match.end()]]
res = res + [s[last:match.start()]] + ['<NUM>']
print( s[match.start():match.end()] )
last = match.end()
print(res)
print(src)
1234 567 89 ['', '<NUM>', '.. еще немного', '<NUM>', '... ошибка 045..и вот завершающий', '<NUM>'] ['', '1234', '.. еще немного', ' 567', '... ошибка 045..и вот завершающий', ' 89']
Собственным циклом
s = '23+56*8-6/3+8'
rnum = '(?P<NUM>[1-9]+[0-9]*)'
rops = '(?P<OP>[+-/*//])'
rr = rnum + '|' + rops
match = re.search( rr, ss)
res = []
src = []
last = 0
for match in re.finditer( rr, s):
src = src + [s[last:match.start()]] + [s[match.start():match.end()]]
res = res + [s[last:match.start()]]
ans = match.groups()
if ans[0]:
res += ['<NUM>']
elif ans[1]:
res += ['<OP>']
last = match.end()
print(res)
print(src)
['', '<NUM>', '', '<OP>', '', '<NUM>', '', '<OP>', '', '<NUM>', '', '<OP>', '', '<NUM>', '', '<OP>', '', '<NUM>', '', '<OP>', '', '<NUM>'] ['', '23', '', '+', '', '56', '', '*', '', '8', '', '-', '', '6', '', '/', '', '3', '', '+', '', '8']
res = [i for i in res if len(i)]# Уберем пустые строки.
res
['<NUM>', '<OP>', '<NUM>', '<OP>', '<NUM>', '<OP>', '<NUM>', '<OP>', '<NUM>', '<OP>', '<NUM>']
src = [i for i in src if len(i)]
src
['23', '+', '56', '*', '8', '-', '6', '/', '3', '+', '8']
len(src), len(res)
(11, 11)
i = 0
while i < len(res):
if res[i] == '<OP>':
if src[i] == '*':
v = float(src[i-1]) * float(src[i+1])
elif src[i] == '/':
v = float(src[i-1]) / float(src[i+1])
else:
i += 1
continue
src[i-1:i+2] = [v]
res[i-1:i+2] = ['<NUM>']
i -= 2
i += 1
src
['23', '+', 448.0, '-', 2.0, '+', '8']
i = 0
while i < len(res):
if res[i] == '<OP>':
if src[i] == '+':
v = float(src[i-1]) + float(src[i+1])
elif src[i] == '-':
v = float(src[i-1]) - float(src[i+1])
else:
i += 1
continue
src[i-1:i+2] = [v]
res[i-1:i+2] = ['<NUM>']
i -= 2
i += 1
src
[477.0]
23+56*8-6/3+8
477.0
Методом
s
'23+56*8-6/3+8'
tkns = re.findall(rr, '23+7-5+99-56*2-7+21/7+6-2*3')
tkns
[('23', ''), ('', '+'), ('7', ''), ('', '-'), ('5', ''), ('', '+'), ('99', ''), ('', '-'), ('56', ''), ('', '*'), ('2', ''), ('', '-'), ('7', ''), ('', '+'), ('21', ''), ('', '/'), ('7', ''), ('', '+'), ('6', ''), ('', '-'), ('2', ''), ('', '*'), ('3', '')]
ops = []
nums = []
while len(tkns) or len(ops):
print("?", ops, nums)
val = None
if len(tkns):
val = tkns.pop(0)
if val[1]=='':
nums.append(val[0])
continue
elif val[1] in ['*','/']:
ops.append(val[1])
continue
elif val[1] in ['+','-']:
pass
while len(ops):
print('<<', ops, nums)
val2 = ops.pop()
##print(val2)
v1 = float(nums.pop())
v2 = float(nums.pop())
if val2 == '/':
vv = v2/v1
elif val2 == '*':
vv = v1*v2
elif val2 == '+':
vv = v2+v1
elif val2 == '-':
vv = v2-v1
nums.append(vv)
print('>>', ops, nums)
if val != None:
ops.append(val[1])
? [] [] ? [] ['23'] ? ['+'] ['23'] ? ['+'] ['23', '7'] << ['+'] ['23', '7'] >> [] [30.0] ? ['-'] [30.0] ? ['-'] [30.0, '5'] << ['-'] [30.0, '5'] >> [] [25.0] ? ['+'] [25.0] ? ['+'] [25.0, '99'] << ['+'] [25.0, '99'] >> [] [124.0] ? ['-'] [124.0] ? ['-'] [124.0, '56'] ? ['-', '*'] [124.0, '56'] ? ['-', '*'] [124.0, '56', '2'] << ['-', '*'] [124.0, '56', '2'] >> ['-'] [124.0, 112.0] << ['-'] [124.0, 112.0] >> [] [12.0] ? ['-'] [12.0] ? ['-'] [12.0, '7'] << ['-'] [12.0, '7'] >> [] [5.0] ? ['+'] [5.0] ? ['+'] [5.0, '21'] ? ['+', '/'] [5.0, '21'] ? ['+', '/'] [5.0, '21', '7'] << ['+', '/'] [5.0, '21', '7'] >> ['+'] [5.0, 3.0] << ['+'] [5.0, 3.0] >> [] [8.0] ? ['+'] [8.0] ? ['+'] [8.0, '6'] << ['+'] [8.0, '6'] >> [] [14.0] ? ['-'] [14.0] ? ['-'] [14.0, '2'] ? ['-', '*'] [14.0, '2'] ? ['-', '*'] [14.0, '2', '3'] << ['-', '*'] [14.0, '2', '3'] >> ['-'] [14.0, 6.0] << ['-'] [14.0, 6.0] >> [] [8.0]
ops, nums
([], [8.0])
23+56*2-7+21/7+6
137.0
23+7-5+99-56*2-7+21/7+6-2*3
8.0
Упр. Добавить обработку возведения в степень ^. Ну и скобки хотелось бы.