## 2. Цикл по перечислению – управляющая инструкция for.
## 2. Ввод данных с клавиатуры.
***Общее правило написания:***
for <Объект-переменная цикла> in <объект>:
<отступы><Блок инструкций 1 – тело цикла>
[else:
< отступы ><Блок инструкций 2 – если в цикле не сработал break>]
### 2.1. Для ввода используйте уже знакомую функцию input.
>Здесь <объект> - любой определенный до начала цикла объект из классов строка, список, кортеж, множество, словарь. <Объект-переменная цикла> - объект, в качестве значений которого поочередно будут задаваться элементы объекта, которые могут быть объектами любого типа. <Блок инструкций 1 – тело цикла> - совокупность инструкций, которая может содержать или не содержать инструкцию break, вызывающую досрочное завершение цикла при некоторых условиях. Блок инструкций 1 обычно выполняется многократно по мере того, как объект-переменная цикла принимает значения из сложного объекта. Если в цикле имеется необязательная часть: else и Блок инструкций 2, то он будет выполняться перед завершением цикла только в том случае, если при выполнении цикла не было его прерывания по инструкции break.
Если Блоке инструкций 1 или в Блоке инструкций 2 только одна инструкция, то её можно записывать без отступов сразу за двоеточием.
```python
psw=input('Введите пароль:')
print(psw)
print(type(psw))
```
Ответ программы:
```shell
Введите пароль:123
123
<class'str'>
```
### 2.2. Ввод с контролем значения.
### 2.1. Простой цикл.
*Пусть вводится число, которое должно находиться в интервале значений от 17.5 до 23.8.*
```python
temperatura=5
for i in range(3,18,3):
temperatura+=i
print(temperatura)
while True:
znach=float(input('Задайте коэф.усиления = '))
if znach<17.5orznach>23.8:
print('Ошибка!')
else:
break
```
Ответ программы:
```shell
50
Задайте коэф.усиления = 15.4
Ошибка!
Задайте коэф.усиления = 21.6
```
### 2.2. Более сложный цикл.
### 2.3. Ввод и обработка выражения, подлежащего расчету.
```python
sps=[2,15,14,8]
for k in sps:
if len(sps)<=10:sps.append(sps[0])
else: break
print("После первого цикла:",sps)
sps=[2,15,14,8]
for k in sps[:]:
if len(sps)<=10:sps.append(sps[0])
else: break
print("После второго цикла:",sps)
import math
print(eval(input('введите выражение для расчета = ')))
```
Ответ программы:
```shell
После первого цикла: [2, 15, 14, 8, 2, 2, 2, 2, 2, 2, 2]
После второго цикла: [2, 15, 14, 8, 2, 2, 2, 2]
введите выражение для расчета = math.log10(23/(1+math.exp(-3.24)))
1.34504378689765
```
>Во втором варианте итерация происходит по неизменяемой копии списка, поэтому цикл выполняется полное количество раз (4 раза), тогда как в первом варианте итерация происходит по изменяемому списку, и цикл завершается досрочно (через break, иначе цикл был бы бесконечным).
## 3. Ввод-вывод при работе с файлами.
***Работа с файлом требует указания источника данных - полного имени файла с путем доступа к его расположению. Обычно наибольшие затруднения вызывает корректная локализация этого пути.***
### 3.1. Функции для работы с путем к файлу.
### 2.3. Пример: создание списка с 10 целыми случайными числами из диапазона от 1 до 100. При этом, если сумма чисел не превышает 500, эта сумма должна быть отображена на экране.
>Эти функции собраны в модуле os. Поэтому при работе с файлами надо импортировать этот модуль командой.Эти функции собраны в модуле os. Поэтому при работе с файлами надо импортировать этот модуль командой
import os
Как и в других системах, в среде Python в любой момент времени подразумевается некоторый рабочий каталог. Какой рабочий каталог установлен в текущий момент времени? Это можно узнать с помощью функции
os.getcwd (cwd = current working directory).
os.getcwd()
Сохраните этот путь в переменной с именем, совпадающим с вашей фамилией в латинской транскрипции. Отобразите её значение с помощью функции print.
*Изменить расположение рабочего каталога можно обращением к уже многократно применявшейся функции os.chdir, аргументом которой будет символьная строка с указанием пути к каталогу, назначаемому в качестве рабочего.*
*Выделить имя файла/конечной директории из этой строки с отбрасыванием пути можно с помощью функции os.path.basename:*
```python
stroka='Это – автоматизированная система'
stroka1=""
for ss in stroka:
stroka1+=" "+ss
print(stroka1)
import os
fil=os.path.abspath("report.md")
drkt=os.path.dirname(fil)
print(os.path.basename(drkt))
```
Ответ программы:
```shell
Э т о – а в т о м а т и з и р о в а н н а я с и с т е м а
python-labs
```
### 2.5. Запись цикла в строке. Пример: создание списка с синусоидальным сигналом.
*Функция os.path.split разделяет путь к файлу или директории на корневую часть пути и имя файла или имя директории. Возвращает кортеж, содержащий два элемента:*
```python
import math
import pylab
import os
fil=os.path.abspath("report.md")
drkt=os.path.dirname(fil)
print(os.path.split(drkt))
print(type(os.path.split(drkt)))
```
sps2 = [math.sin(i * math.pi / 5 + 2) for i in range(100)]
*С помощью функции os.path.exists можно проверить существует ли путь, заданный в символьной строке – аргументе функции. Возвращаемое значение: True или False.*
pylab.plot(sps2)
pylab.title('Синусоидальный сигнал')
pylab.xlabel('Отсчеты')
pylab.ylabel('Амплитуда')
pylab.grid(True)
pylab.show()
```python
import os
fil=os.path.abspath("report.md")
drkt=os.path.dirname(fil)
print(os.path.exists(drkt + "/TEMA6"))
print(os.path.exists(drkt + "/TEMA66"))
```
Ответ программы:

```shell
True
False
```
## 3. Цикл «пока истинно условие» – управляющая инструкция while.
*Проверьте наличие файла с известным расположением с помощью функции os.path.isfile, аргументом которой должна быть символьная строка с путем и именем интересующего файла. Возвращаемое значение: True или False.*
***Общее правило написания:***
while <Условие>:
<отступы><Блок инструкций 1 – тело цикла>
[else:
<отступы><Блок инструкций 2 – если в цикле не сработал break>]
>Здесь <Условие> - некоторое логическое выражение. Если на очередном витке цикла оно принимает значение True (или ≠0), то выполняется Блок инструкций 1. При этом, если в этом блоке присутствует инструкция break и она будет выполнена, то цикл завершается, иначе – переходит к новому витку цикла. В блоке инструкций 1 могут быть изменены значения объектов, входящих в Условие и его значение тоже может измениться, Если же его значением останется True, то вновь выполняется Блок инструкций 1 и т.д. Если в цикле присутствует Блок инструкций 2, то он будет выполнен, если завершение цикла произошло не по инструкции break, а по значению False (или значению =0) Условия.
```python
import os
fil=os.path.abspath("report.md")
drkt=os.path.dirname(fil)
print(os.path.isfile(drkt + "/TEMA6/report.md"))
print(os.path.isfile(drkt + "/TEMA6/report1.md"))
```
### 3.1. Цикл со счётчиком.
Ответ программы:
```shell
True
False
```
## 4. Общая схема работы с файлом.
*Для обмена данными с файлом необходимо выполнить следующие операции:*
* Открытие файла с указанием его имени и цели (чтение, запись, добавление данных);
* Выполнение одной или нескольких операций обмена данными с файлом;
* Закрытие файла.
### 4.1. Открытие файла для записи или чтения данных – функция open.
*При открытии файла необходимо указать имя файлы (с путем, если он не в рабочем каталоге) и цель работы с ним. Для открытия используется функция open.*
The default mode is 'rt' (open for reading text). For binary random
access, the mode 'w+b' opens and truncates the file to 0 bytes, while
'r+b' opens the file without truncation. The 'x' mode implies 'w' and
raises an `FileExistsError` if the file already exists.
```
*Откройте файл zapis1.txt для записи данных с помощью инструкции*
```python
import os
fil=os.path.abspath("report.md")
drkt=os.path.dirname(fil)
fp=open(file=drkt+'/TEMA6/zapis1.txt',mode='w')
```
Цикл завершился, потому что в Python число 0 интерпретируется как логическое значение False.
Ответ программы:

*Здесь fp – это файловый объект, который в других языках программирования обычно называют файловой переменной. Он сохраняет ссылку на открываемый файл и позволяет в дальнейшем ссылаться на файл, не указывая путь и имя открытого файла. В аргументе функции с именем file указывается путь и имя открываемого файла, а в аргументе с именем mode – предполагаемая цель его использования (w=write – для записи).*
### 3.2. Пример с символьной строкой.
*Если путь в переменной drkt совпадает с рабочим каталогом, то его можно опустить, оставив только имя открываемого файла:*
Если требуются другие операции с открываемым файлом, то для второго аргумента «mode=…» могут быть заданы следующие значения:
w – запись с созданием нового файла или перезапись существующего файла,
w+ - чтение и запись/перезапись файла,
r – только чтение (это значение - по умолчанию),
r+ - чтение и/или запись в существующий файл,
a – запись в конец существующего файла или, если его нет, запись с созданием файла,
a+ - то же, что и в «a», но с возможностью чтения из файла.
В зависимости от значения этого аргумента тип создаваемой файловой переменной может быть разным.
*Создаваемые и читаемые файлы могут быть бинарными или символьными. При открытии бинарного файла к указанным выше буквам в аргументе-цели надо добавить символ «b».*
```python
import os
fil=os.path.abspath("report.md")
drkt=os.path.dirname(fil)
fp1=open(drkt+'/TEMA6/zapis2.bin',mode='wb+')
```
Ответ программы:


***В бинарный файл можно без преобразования записывать объекты любого типа.***
### 3.3. Определение, является ли число простым (делится только на самого себя или 1).
*Если файл – символьный, то его тип обозначается «t», но это – значение по умолчанию и его можно не указывать. В символьный файл можно записывать только объекты типа str. Объекты других типов надо перед записью преобразовать к этому типу.*
### 4.2. Закрытие файла.
*Сразу после завершения работы с файлом его следует закрыть для обеспечения сохранности его содержимого. Это делается с помощью метода close, применяемого к объекту – файловой переменной.*
```python
fp.close()
```
### 4.3. Запись информации в файл с помощью метода write.
***Метод write относится к объекту – файловой переменной.***
```python
# Проверка одного числа
chislo = 267
kandidat = chislo // 2
while kandidat > 1:
if chislo % kandidat == 0:
print(chislo, ' имеет множитель ', kandidat)
break
kandidat -= 1
else:
print(chislo, ' является простым!')
import os
fil=os.path.abspath("report.md")
drkt=os.path.dirname(fil)
sps=list(range(1,13))
fp=open(file=drkt+'/TEMA6/zapis3.txt',mode='w')
fp.write(str(sps[:4])+'\n')
fp.write(str(sps[4:8])+'\n')
fp.write(str(sps[8:])+'\n')
fp.close()
```
Файл zapis3.txt:
```
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11, 12]
print("\nПростые числа в диапазоне от 250 до 300:")
*Информация в текстовом файле размещена последовательно, по строкам, с завершением каждой строки символом ‘\n’ (конец строки). При чтении из файла из него извлекается часть информации, начиная с некоторого символа. Обычно, для удобства, считают, что перед этим символом стоит невидимый маркер (указатель), который при открытии файла устанавливается перед первым символом. После чтения части информации маркер перемещается и ставится перед символом, следующим за прочитанной частью информации.*
### 5.2. Чтение информации из файла с помощью метода read.
*Метод read, как и write, относится к объекту – файловой переменной. В качестве аргумента этого метода может задаваться целое число – количество символов или, если открыт бинарный файл, - количество байт, которое должно быть прочитано, соответственно, из текстового или бинарного файла, начиная с текущего положения маркера. Если указанное число превышает количество оставшихся символов (байт) в файле, то считываются все оставшиеся символы (байты). Если это число не указано, то считываются вся информация от маркера до конца файла. Метод возвращает строку с символами или совокупность байт, прочитанных из файла.*
### 5.3. Чтение информации с помощью методов readline и readlines.
*Эти методы позволяют прочитать из файла, начиная с текущего положения маркера, соответственно, одну строку символов (совокупность байт) или все строки (все байты).*
## 6. Ввод-вывод объектов с использованием функций из модуля pickle.
*В модуле pickle содержатся функции для работы с бинарными файлами, в которые могут последовательно записываться или считываться целиком один или несколько объектов из оперативной памяти.*
### 6.1. Запись.
```python
import os
import pickle
mnoz1={'pen','book','pen','iPhone','table','book'} #Объект типа «множество»
fp=open(os.path.dirname(os.path.abspath("report.md")) + '/TEMA6/zapis6.mnz','wb') # Бинарный файл – на запись
pickle.dump(mnoz1,fp) #dump – метод записи объекта в файл
mnoz2=pickle.load(fp) #load – метод чтения объекта из бинарного файла
fp.close()
print(mnoz2, '\n')
print(mnoz1==mnoz2)
print(mnoz1 is mnoz2)
```
### 3.4. Continue.
Ответ программы:
```shell
{'book', 'iPhone', 'table', 'pen'}
{'book', 'iPhone', 'table', 'pen'}
True
False
```
>Помимо инструкции break в обоих видах циклов могут использоваться инструкции continue, которые не вызывают завершения цикла, но завершают его текущий виток и обеспечивают переход к следующему витку.
**Почему порядок элементов отличается от исходного?**
Пример: Вывод четных чисел от 1 до 10 с использованием continue.
* Множество (set) в Python - неупорядоченная коллекция
* Элементы хранятся в порядке, оптимизированном для быстрого поиска
* Порядок зависит от хэш-значений элементов и может меняться между запусками
* Исходный порядок {'pen','book','iPhone','table'} не сохраняется
**Почему удалились дубликаты?**
* Множество автоматически удаляет повторяющиеся элементы
* Стало: {'pen','book','iPhone','table'} (4 элемента вместо 6)
**Проверка совпадения:**
* mnoz1 == mnoz2: True - объекты содержат одинаковые элементы
* mnoz1 is mnoz2: False - это разные объекты в памяти
### 6.3. Запись и чтение.
*Теперь с использованием тех же функций запишите в файл, а затем прочитайте два объекта разных типов: то же множество mnoz1 и ранее созданный список sps3. При считывании объекты извлекаются из файла в той же последовательности, в которой они в него записывались.*