HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-21
1 <p><a>#База знаний</a></p>
1 <p><a>#База знаний</a></p>
2 <ul><li>25 май 2021</li>
2 <ul><li>25 май 2021</li>
3 <li>0</li>
3 <li>0</li>
4 </ul><p>Чтобы код оставался понятным, в нём регулярно надо убираться. Рассказываем, что и где прибирать.</p>
4 </ul><p>Чтобы код оставался понятным, в нём регулярно надо убираться. Рассказываем, что и где прибирать.</p>
5 <p>Программист, консультант, специалист по документированию. Легко и доступно рассказывает о сложных вещах в программировании и дизайне.</p>
5 <p>Программист, консультант, специалист по документированию. Легко и доступно рассказывает о сложных вещах в программировании и дизайне.</p>
6 <p>Программисты знают, как трудно при разработке приложения сохранить чистоту и хорошую структуру кода. Из-за спешных доработок, которые к тому же делают разные люди, даже простой и продуманный исходник часто становится запутанным и непонятным. И в нём уже настолько сложно разобраться, что проще написать всё заново.</p>
6 <p>Программисты знают, как трудно при разработке приложения сохранить чистоту и хорошую структуру кода. Из-за спешных доработок, которые к тому же делают разные люди, даже простой и продуманный исходник часто становится запутанным и непонятным. И в нём уже настолько сложно разобраться, что проще написать всё заново.</p>
7 <p>Чтобы не допустить этого, при разработке периодически проводят<strong>рефакторинг</strong> - вносят изменения, которые делают код понятнее, но не меняют его функциональность.</p>
7 <p>Чтобы не допустить этого, при разработке периодически проводят<strong>рефакторинг</strong> - вносят изменения, которые делают код понятнее, но не меняют его функциональность.</p>
8 <p><strong>Важно!</strong>Рефакторинг более эффективен и безопасен, когда пошаговые изменения проверяются запусками тестов.</p>
8 <p><strong>Важно!</strong>Рефакторинг более эффективен и безопасен, когда пошаговые изменения проверяются запусками тестов.</p>
9 <p>Если вы только-только столкнулись с рефакторингом - сперва<a>прочтите эту статью</a>.</p>
9 <p>Если вы только-только столкнулись с рефакторингом - сперва<a>прочтите эту статью</a>.</p>
10 <p>В языке Python есть много приёмов улучшения кода. Однако перед тем, как применять более сложные, нужно почистить код от накопившегося мусора.</p>
10 <p>В языке Python есть много приёмов улучшения кода. Однако перед тем, как применять более сложные, нужно почистить код от накопившегося мусора.</p>
11 <p>Удаляйте закомментированные куски кода. Они сбивают с толку разработчиков, которые работают с исходниками после вас.</p>
11 <p>Удаляйте закомментированные куски кода. Они сбивают с толку разработчиков, которые работают с исходниками после вас.</p>
12 <p>Например, вы попробовали вариант решения задачи, но потом решили сделать всё по-другому. Промежуточные куски кода вы закомментировали - а вдруг пригодятся. Не стоит так делать. Если понадобится, лучше посмотреть предыдущую версию кода в системе контроля версий.</p>
12 <p>Например, вы попробовали вариант решения задачи, но потом решили сделать всё по-другому. Промежуточные куски кода вы закомментировали - а вдруг пригодятся. Не стоит так делать. Если понадобится, лучше посмотреть предыдущую версию кода в системе контроля версий.</p>
13 <p>Это тоже мусор. Если они всего лишь помогали вам увидеть промежуточные результаты, то их следует удалить сразу после того, как вы разобрались в работе программы.</p>
13 <p>Это тоже мусор. Если они всего лишь помогали вам увидеть промежуточные результаты, то их следует удалить сразу после того, как вы разобрались в работе программы.</p>
14 <p>Допустим, вы попробовали вариант решения с использованием каких-то модулей, потом пошли по другому пути и модули более не нужны.</p>
14 <p>Допустим, вы попробовали вариант решения с использованием каких-то модулей, потом пошли по другому пути и модули более не нужны.</p>
15 <p>Не забудьте удалить из кода соответствующие команды импорта - обычно редакторы их подсвечивают. Так, в IDE<a>PyCharm</a>текст команды становится бледным и при компиляции выдаётся предупреждение "Unused import statement…".</p>
15 <p>Не забудьте удалить из кода соответствующие команды импорта - обычно редакторы их подсвечивают. Так, в IDE<a>PyCharm</a>текст команды становится бледным и при компиляции выдаётся предупреждение "Unused import statement…".</p>
16 <p>Это такие переменные, которые создаются, но нигде не применяются. Они могут остаться после исправления кода или по окончании рефакторинга. Их тоже нужно убирать.</p>
16 <p>Это такие переменные, которые создаются, но нигде не применяются. Они могут остаться после исправления кода или по окончании рефакторинга. Их тоже нужно убирать.</p>
17 <p>Найти эти переменные легко - редакторы их подсвечивают, а при компиляции выдаётся предупреждение: "Variable is not used".</p>
17 <p>Найти эти переменные легко - редакторы их подсвечивают, а при компиляции выдаётся предупреждение: "Variable is not used".</p>
18 <p>Например:</p>
18 <p>Например:</p>
19 <p>Здесь PyCharm выделяет серым и ненужный модуль os, и неиспользуемые переменные unused1 и unused2.</p>
19 <p>Здесь PyCharm выделяет серым и ненужный модуль os, и неиспользуемые переменные unused1 и unused2.</p>
20 <p>Проводя рефакторинг, важно оформить код так, чтобы его было удобно читать.</p>
20 <p>Проводя рефакторинг, важно оформить код так, чтобы его было удобно читать.</p>
21 <p>Создатель языка Python Гвидо ван Россум сказал: "Код читают гораздо чаще, чем пишут".</p>
21 <p>Создатель языка Python Гвидо ван Россум сказал: "Код читают гораздо чаще, чем пишут".</p>
22 <p>Действительно, вы написали кусок кода за раз, но, когда он станет частью проекта, его придётся перечитывать снова и снова - вспоминая, что он делает и почему так написан. Это придётся делать не только вам, но и вашим коллегам. Поэтому важно сделать код удобочитаемым - для всех.</p>
22 <p>Действительно, вы написали кусок кода за раз, но, когда он станет частью проекта, его придётся перечитывать снова и снова - вспоминая, что он делает и почему так написан. Это придётся делать не только вам, но и вашим коллегам. Поэтому важно сделать код удобочитаемым - для всех.</p>
23 <p>Гвидо ван Россум считал удобочитаемость одним из важнейших принципов языка Python. Поэтому вместе с соратниками разработал<strong>свод рекомендаций по оформлению кода -</strong><a><strong>PEP 8</strong></a>. Рассмотрим некоторые из них подробнее.</p>
23 <p>Гвидо ван Россум считал удобочитаемость одним из важнейших принципов языка Python. Поэтому вместе с соратниками разработал<strong>свод рекомендаций по оформлению кода -</strong><a><strong>PEP 8</strong></a>. Рассмотрим некоторые из них подробнее.</p>
24 <p>Конечно, программист - хозяин своей программы и может именовать переменные, константы, функции и классы по своему разумению. Но стоит помнить, что бессодержательные имена затрудняют понимание кода. Поэтому следует подбирать их так, чтобы другой программист быстрее понял, для чего они нужны.</p>
24 <p>Конечно, программист - хозяин своей программы и может именовать переменные, константы, функции и классы по своему разумению. Но стоит помнить, что бессодержательные имена затрудняют понимание кода. Поэтому следует подбирать их так, чтобы другой программист быстрее понял, для чего они нужны.</p>
25 <p>Например, имя переменной в выражении sc += 1 нам мало о чём говорит.</p>
25 <p>Например, имя переменной в выражении sc += 1 нам мало о чём говорит.</p>
26 <p>А если изменить его на score, то станет ясно, что речь идёт о счёте.</p>
26 <p>А если изменить его на score, то станет ясно, что речь идёт о счёте.</p>
27 <p>Есть два важнейших правила именования сущностей в Python - их нарушение вызывает ошибку:</p>
27 <p>Есть два важнейших правила именования сущностей в Python - их нарушение вызывает ошибку:</p>
28 <ul><li>имена могут состоять только из цифр, букв и знаков подчёркивания;</li>
28 <ul><li>имена могут состоять только из цифр, букв и знаков подчёркивания;</li>
29 <li>имя не может начинаться с цифры.</li>
29 <li>имя не может начинаться с цифры.</li>
30 </ul><p>PEP 8<a>предписывает</a>задавать имена определённым образом:</p>
30 </ul><p>PEP 8<a>предписывает</a>задавать имена определённым образом:</p>
31 <ul><li>Имена функций и модулей пишутся строчными буквами. Они могут состоять из одного или нескольких слов, которые разделяются подчёркиванием (например: function, my_function).</li>
31 <ul><li>Имена функций и модулей пишутся строчными буквами. Они могут состоять из одного или нескольких слов, которые разделяются подчёркиванием (например: function, my_function).</li>
32 <li>Имена переменных тоже задаются в нижнем регистре. Они могут состоять из одной буквы, слова или нескольких слов. Слова в составе имени тоже разделяются подчёркиванием: x, variable, my_var.</li>
32 <li>Имена переменных тоже задаются в нижнем регистре. Они могут состоять из одной буквы, слова или нескольких слов. Слова в составе имени тоже разделяются подчёркиванием: x, variable, my_var.</li>
33 <li>Название константы задаётся символом, словом или несколькими словами в верхнем регистре. Слова в составе имени разделяются знаком подчёркивания.<p>Например:</p>
33 <li>Название константы задаётся символом, словом или несколькими словами в верхнем регистре. Слова в составе имени разделяются знаком подчёркивания.<p>Например:</p>
34 C, CONST, MY_CONST.</li>
34 C, CONST, MY_CONST.</li>
35 <li>Имена классов состоят из одного (Class) или нескольких слов (MyClass) без разделителей.<p>Во втором случае, как вы заметили, каждое слово начинается с прописной буквы. Такой стиль называется<strong>CamelCase</strong>("верблюжий стиль").</p>
35 <li>Имена классов состоят из одного (Class) или нескольких слов (MyClass) без разделителей.<p>Во втором случае, как вы заметили, каждое слово начинается с прописной буквы. Такой стиль называется<strong>CamelCase</strong>("верблюжий стиль").</p>
36 </li>
36 </li>
37 <li>Имена модулей задаются в нижнем регистре. Они не должны быть длинными. Знак подчёркивания уместен, если с ним имя модуля читабельнее, а его назначение понятнее.<p>Например:</p>
37 <li>Имена модулей задаются в нижнем регистре. Они не должны быть длинными. Знак подчёркивания уместен, если с ним имя модуля читабельнее, а его назначение понятнее.<p>Например:</p>
38 pyclbr, py_compile.</li>
38 pyclbr, py_compile.</li>
39 </ul><ul></ul><p>PEP 8 описывает и <a>принципы оформления кода</a>:</p>
39 </ul><ul></ul><p>PEP 8 описывает и <a>принципы оформления кода</a>:</p>
40 <ul><li>как отделять функции и классы от остального текста;</li>
40 <ul><li>как отделять функции и классы от остального текста;</li>
41 <li>какой должна быть максимальная длина строки, как правильно разбивать длинные строки;</li>
41 <li>какой должна быть максимальная длина строки, как правильно разбивать длинные строки;</li>
42 <li>какими должны быть отступы;</li>
42 <li>какими должны быть отступы;</li>
43 <li>где ставить пробелы в выражениях и утверждениях</li>
43 <li>где ставить пробелы в выражениях и утверждениях</li>
44 <li>и другие.</li>
44 <li>и другие.</li>
45 </ul><p>Обнаружить ошибки форматирования помогают специальные программы -<strong>линтеры</strong>. Они анализируют код и выдают предупреждения, например:</p>
45 </ul><p>Обнаружить ошибки форматирования помогают специальные программы -<strong>линтеры</strong>. Они анализируют код и выдают предупреждения, например:</p>
46 <p>Здесь<strong>линтер flake8</strong>в PyCharm выдаёт предупреждения о лишних пробелах внутри скобок и перед ними.</p>
46 <p>Здесь<strong>линтер flake8</strong>в PyCharm выдаёт предупреждения о лишних пробелах внутри скобок и перед ними.</p>
47 <p>Для разных языков программирования есть свои линтеры. Например, для HTML - Beautify, для JavaScript - JSLint и так далее.</p>
47 <p>Для разных языков программирования есть свои линтеры. Например, для HTML - Beautify, для JavaScript - JSLint и так далее.</p>
48 <p>Популярные линтеры для Python:</p>
48 <p>Популярные линтеры для Python:</p>
49 <ul><li><a>Pycodestyle</a>,</li>
49 <ul><li><a>Pycodestyle</a>,</li>
50 <li><a>Pyflakes</a>,</li>
50 <li><a>Pyflakes</a>,</li>
51 <li><a>Pylint</a>,</li>
51 <li><a>Pylint</a>,</li>
52 <li><a>Flake8</a>.</li>
52 <li><a>Flake8</a>.</li>
53 </ul><p>Все они легко интегрируются в среды разработки. А самым умным считается<strong>pylint</strong>. Он проверяет:</p>
53 </ul><p>Все они легко интегрируются в среды разработки. А самым умным считается<strong>pylint</strong>. Он проверяет:</p>
54 <ul><li>все ли подключённые модули используются в программе;</li>
54 <ul><li>все ли подключённые модули используются в программе;</li>
55 <li>есть ли лишние переменные;</li>
55 <li>есть ли лишние переменные;</li>
56 <li>не превышает ли длина строк 79 символов;</li>
56 <li>не превышает ли длина строк 79 символов;</li>
57 <li>правильно ли заданы имена;</li>
57 <li>правильно ли заданы имена;</li>
58 <li>верно ли используются аргументы;</li>
58 <li>верно ли используются аргументы;</li>
59 <li>есть ли синтаксические ошибки;</li>
59 <li>есть ли синтаксические ошибки;</li>
60 <li>как используются типы данных</li>
60 <li>как используются типы данных</li>
61 <li>и многое другое.</li>
61 <li>и многое другое.</li>
62 </ul><p>Обнаруженные ошибки можно исправить вручную или с помощью утилит для форматирования кода -<strong>форматтеров</strong>, которые совместимы с IDE PyCharm или Visual Studio.</p>
62 </ul><p>Обнаруженные ошибки можно исправить вручную или с помощью утилит для форматирования кода -<strong>форматтеров</strong>, которые совместимы с IDE PyCharm или Visual Studio.</p>
63 <p>Популярные форматтеры:</p>
63 <p>Популярные форматтеры:</p>
64 <ul><li><a>Autopep8</a>,</li>
64 <ul><li><a>Autopep8</a>,</li>
65 <li><a>YAPF</a>,</li>
65 <li><a>YAPF</a>,</li>
66 <li><a>Black</a>.</li>
66 <li><a>Black</a>.</li>
67 </ul><p>Если похожие участки кода (или делающий то же самое код) встречаются в нескольких местах программы, это и есть дублирование.</p>
67 </ul><p>Если похожие участки кода (или делающий то же самое код) встречаются в нескольких местах программы, это и есть дублирование.</p>
68 <p>Дублирование часто возникает, когда несколько человек работают в проекте над схожими задачами и не знают, что коллега где-то уже написал нужный код.</p>
68 <p>Дублирование часто возникает, когда несколько человек работают в проекте над схожими задачами и не знают, что коллега где-то уже написал нужный код.</p>
69 <p>А ещё повторами часто грешат начинающие программисты. Они видят в проекте почти такой же код, как нужен им, и копируют его в другое место, немного изменив. Это приводит к проблемам:</p>
69 <p>А ещё повторами часто грешат начинающие программисты. Они видят в проекте почти такой же код, как нужен им, и копируют его в другое место, немного изменив. Это приводит к проблемам:</p>
70 <ul><li>Возникают куски одинакового текста, различающиеся лишь некоторыми строками или символами - и не сразу понятно какими. Это затрудняет понимание программы.</li>
70 <ul><li>Возникают куски одинакового текста, различающиеся лишь некоторыми строками или символами - и не сразу понятно какими. Это затрудняет понимание программы.</li>
71 <li>Текст программы раздувается, в нём труднее разобраться.</li>
71 <li>Текст программы раздувается, в нём труднее разобраться.</li>
72 <li>Когда нужно менять функциональность, за которую отвечает дублирующийся код, изменения приходится вносить сразу во много мест программы. Это чревато ошибками.</li>
72 <li>Когда нужно менять функциональность, за которую отвечает дублирующийся код, изменения приходится вносить сразу во много мест программы. Это чревато ошибками.</li>
73 </ul><p>Чтобы избавиться от дублирования, применяют приём рефакторинга "извлечение метода": дублирующийся участок выносят в отдельный метод или функцию и везде заменяют вызовом этого метода/функции.</p>
73 </ul><p>Чтобы избавиться от дублирования, применяют приём рефакторинга "извлечение метода": дублирующийся участок выносят в отдельный метод или функцию и везде заменяют вызовом этого метода/функции.</p>
74 <p>Рассмотрим на примере:</p>
74 <p>Рассмотрим на примере:</p>
75 while True : a1 = int(input( "Введите цену товара: ")) if a1 &lt; 0 : print ("Значение не должно быть отрицательным!") else : break while True : a2 = int(input("Введите количество товара: ")) if a2 &lt; 0 : print ("Значение не должно быть отрицательным!") else : break a3 = a1 * a2 print("Стоимость товара: ", a3)<p>Этот код явно нуждается в рефакторинге. И вот почему:</p>
75 while True : a1 = int(input( "Введите цену товара: ")) if a1 &lt; 0 : print ("Значение не должно быть отрицательным!") else : break while True : a2 = int(input("Введите количество товара: ")) if a2 &lt; 0 : print ("Значение не должно быть отрицательным!") else : break a3 = a1 * a2 print("Стоимость товара: ", a3)<p>Этот код явно нуждается в рефакторинге. И вот почему:</p>
76 <ul><li>два блока выполняют практически одинаковые действия;</li>
76 <ul><li>два блока выполняют практически одинаковые действия;</li>
77 <li>названия переменных a1, a2, a3 не говорят об их предназначении.</li>
77 <li>названия переменных a1, a2, a3 не говорят об их предназначении.</li>
78 </ul><p>Мы видим в коде два блока, которые отличаются только сообщениями пользователю: "Введите цену товара: " и "Введите количество товара: ".</p>
78 </ul><p>Мы видим в коде два блока, которые отличаются только сообщениями пользователю: "Введите цену товара: " и "Введите количество товара: ".</p>
79 <p>Такое дублирование - это плохо:</p>
79 <p>Такое дублирование - это плохо:</p>
80 <ul><li>Например, поменялись бизнес-правила: нас больше не интересуют товары с нулевой стоимостью. И нужно поставить условие: количество и цена должны быть больше нуля. Нам придётся вносить изменения в оба блока кода.</li>
80 <ul><li>Например, поменялись бизнес-правила: нас больше не интересуют товары с нулевой стоимостью. И нужно поставить условие: количество и цена должны быть больше нуля. Нам придётся вносить изменения в оба блока кода.</li>
81 <li>Или мы захотим, скажем, добавить в расчёт стоимости скидку/наценку. Тогда нам придётся создать ещё один похожий блок с новым сообщением: "Введите процент скидки (или наценки) на товар: ". А потом ещё один и ещё. Код быстро разрастётся.</li>
81 <li>Или мы захотим, скажем, добавить в расчёт стоимости скидку/наценку. Тогда нам придётся создать ещё один похожий блок с новым сообщением: "Введите процент скидки (или наценки) на товар: ". А потом ещё один и ещё. Код быстро разрастётся.</li>
82 </ul><p>Чтобы упростить код, преобразуем цикл while в функцию, а сообщения для пользователя будем передавать в неё как аргументы. Назовём функцию input_value() ("ввод значения"), добавим в неё команду return a1 и уберём break.</p>
82 </ul><p>Чтобы упростить код, преобразуем цикл while в функцию, а сообщения для пользователя будем передавать в неё как аргументы. Назовём функцию input_value() ("ввод значения"), добавим в неё команду return a1 и уберём break.</p>
83 <p>Вот что у нас выйдет:</p>
83 <p>Вот что у нас выйдет:</p>
84 def input_value() : while True : a1 = int (input("Введите цену товара: ")) if a1 &lt; 0 : print ("Значение не должно быть отрицательным!") else : return a1<p>Чтобы сообщать пользователю, что вводить (цену, количество товара и так далее), вместо приглашения "Введите цену товара: " добавим параметр функции и назовём его prompt ("подсказка").</p>
84 def input_value() : while True : a1 = int (input("Введите цену товара: ")) if a1 &lt; 0 : print ("Значение не должно быть отрицательным!") else : return a1<p>Чтобы сообщать пользователю, что вводить (цену, количество товара и так далее), вместо приглашения "Введите цену товара: " добавим параметр функции и назовём его prompt ("подсказка").</p>
85 <p>Вот что получится:</p>
85 <p>Вот что получится:</p>
86 def input_value(prompt): while True: a1 = int(input(prompt)) if a1 &lt; 0 : print ("Значение не должно быть отрицательным!") else : return a1<p>Теперь заменим одинаковые блоки кода вызовами функции с соответствующими значениями параметра. Сразу же дадим переменным новые, осмысленные имена: value, price, quantity, cost.</p>
86 def input_value(prompt): while True: a1 = int(input(prompt)) if a1 &lt; 0 : print ("Значение не должно быть отрицательным!") else : return a1<p>Теперь заменим одинаковые блоки кода вызовами функции с соответствующими значениями параметра. Сразу же дадим переменным новые, осмысленные имена: value, price, quantity, cost.</p>
87 <p>Исправленный код будет выглядеть так:</p>
87 <p>Исправленный код будет выглядеть так:</p>
88 def input_value(prompt): while True: value = int( input( prompt ) ) if value &lt; 0 : print ("Значение не должно быть отрицательным!") else : return value price = input_value("Введите цену товара: ") quantity = input_value("Введите количество товара: ") cost = price * quantity print("Стоимость товара: ", cost)<p>Переменная cost не используется в дальнейших вычислениях: она всего лишь хранит результат подсчёта стоимости товара для передачи его в качестве аргумента функции print().</p>
88 def input_value(prompt): while True: value = int( input( prompt ) ) if value &lt; 0 : print ("Значение не должно быть отрицательным!") else : return value price = input_value("Введите цену товара: ") quantity = input_value("Введите количество товара: ") cost = price * quantity print("Стоимость товара: ", cost)<p>Переменная cost не используется в дальнейших вычислениях: она всего лишь хранит результат подсчёта стоимости товара для передачи его в качестве аргумента функции print().</p>
89 <p>Поэтому переменную cost можно смело убирать, а в print () передавать выражение price * quantity. Это сократит код, улучшит читабельность и уменьшит используемые ресурсы:</p>
89 <p>Поэтому переменную cost можно смело убирать, а в print () передавать выражение price * quantity. Это сократит код, улучшит читабельность и уменьшит используемые ресурсы:</p>
90 def input_value(prompt): while True: value = int( input( prompt ) ) if value &lt; 0 : print ("Значение не должно быть отрицательным!") else : return value price = input_value ("Введите цену товара: ") quantity = input_value ("Введите количество товара: ") print ("Стоимость товара: ", price * quantity)<p><strong>Важно!</strong>Иногда временные переменные вовсе не бесполезны. Например, когда они служат для кэширования - хранят результат затратной, ресурсоёмкой или длительной операции, который при работе программы используется несколько раз.</p>
90 def input_value(prompt): while True: value = int( input( prompt ) ) if value &lt; 0 : print ("Значение не должно быть отрицательным!") else : return value price = input_value ("Введите цену товара: ") quantity = input_value ("Введите количество товара: ") print ("Стоимость товара: ", price * quantity)<p><strong>Важно!</strong>Иногда временные переменные вовсе не бесполезны. Например, когда они служат для кэширования - хранят результат затратной, ресурсоёмкой или длительной операции, который при работе программы используется несколько раз.</p>
91 <p>Проверьте, что переменная, которую вы собираетесь удалить, не из таких.</p>
91 <p>Проверьте, что переменная, которую вы собираетесь удалить, не из таких.</p>
92 <p>В результате рефакторинга:</p>
92 <p>В результате рефакторинга:</p>
93 <ul><li>мы убрали дублирующийся код,</li>
93 <ul><li>мы убрали дублирующийся код,</li>
94 <li>дали переменным осмысленные имена,</li>
94 <li>дали переменным осмысленные имена,</li>
95 <li>вынесли ввод и проверку значений в отдельную функцию.</li>
95 <li>вынесли ввод и проверку значений в отдельную функцию.</li>
96 </ul><p>Программа стала короче, нагляднее и вдобавок универсальнее. Например, теперь легко добавить скидку в расчёт стоимости товара:</p>
96 </ul><p>Программа стала короче, нагляднее и вдобавок универсальнее. Например, теперь легко добавить скидку в расчёт стоимости товара:</p>
97 def input_value(prompt): while True: value = int( input( prompt ) ) if value &lt; 0 : print ("Значение не должно быть отрицательным!") else : return value price = input_value ("Введите цену товара: ") quantity = input_value ("Введите количество товара: ") discount = input_value ("Введите процент скидки: ") print ("Стоимость товара: ", price * quantity * (1 - discount/100))<p>Рефакторинг не ограничивается чисткой кода и улучшением его структуры. Python - язык гибкий, одну и ту же операцию позволяет реализовать по-разному.</p>
97 def input_value(prompt): while True: value = int( input( prompt ) ) if value &lt; 0 : print ("Значение не должно быть отрицательным!") else : return value price = input_value ("Введите цену товара: ") quantity = input_value ("Введите количество товара: ") discount = input_value ("Введите процент скидки: ") print ("Стоимость товара: ", price * quantity * (1 - discount/100))<p>Рефакторинг не ограничивается чисткой кода и улучшением его структуры. Python - язык гибкий, одну и ту же операцию позволяет реализовать по-разному.</p>
98 <p>Задача рефакториста - выбрать самую краткую и понятную реализацию, которая использует возможности последней версии языка и библиотек.</p>
98 <p>Задача рефакториста - выбрать самую краткую и понятную реализацию, которая использует возможности последней версии языка и библиотек.</p>
99 <p>Рассмотрим несколько простых приёмов рефакторинга, которые позволяют уменьшить объём кода.</p>
99 <p>Рассмотрим несколько простых приёмов рефакторинга, которые позволяют уменьшить объём кода.</p>
100 <p>Для создания списков, словарей и множеств в языке Python часто применяют генераторы. Один из практикуемых приёмов рефакторинга - заменить таким генератором цикл for. Код сокращается, становится нагляднее, к тому же работает быстрее.</p>
100 <p>Для создания списков, словарей и множеств в языке Python часто применяют генераторы. Один из практикуемых приёмов рефакторинга - заменить таким генератором цикл for. Код сокращается, становится нагляднее, к тому же работает быстрее.</p>
101 <p><strong>Пример первый</strong></p>
101 <p><strong>Пример первый</strong></p>
102 <p>Есть список из нескольких чисел. Нам нужно получить список квадратов этих чисел.</p>
102 <p>Есть список из нескольких чисел. Нам нужно получить список квадратов этих чисел.</p>
103 <p>Реализация с использованием цикла:</p>
103 <p>Реализация с использованием цикла:</p>
104 spisok = [1, 25, 44, 213, 14, 27, 56, 8] square_spisok = [] for item in spisok: square_spisok.append(item**2) print(square_spisok) --OUTPUT&gt; [1, 625, 1936, 45369, 196, 729, 3136, 64]<p>После рефакторинга с переходом к генератору:</p>
104 spisok = [1, 25, 44, 213, 14, 27, 56, 8] square_spisok = [] for item in spisok: square_spisok.append(item**2) print(square_spisok) --OUTPUT&gt; [1, 625, 1936, 45369, 196, 729, 3136, 64]<p>После рефакторинга с переходом к генератору:</p>
105 spisok = [1, 25, 44, 213, 14, 27, 56, 8] square_spisok = [item**2 for item in spisok] print(square_spisok) --OUTPUT&gt; [1, 625, 1936, 45369, 196, 729, 3136, 64]<p><strong>Пример второй</strong></p>
105 spisok = [1, 25, 44, 213, 14, 27, 56, 8] square_spisok = [item**2 for item in spisok] print(square_spisok) --OUTPUT&gt; [1, 625, 1936, 45369, 196, 729, 3136, 64]<p><strong>Пример второй</strong></p>
106 <p>Вычисление суммы двух матриц. С циклами реализация выглядит так:</p>
106 <p>Вычисление суммы двух матриц. С циклами реализация выглядит так:</p>
107 a = [[1, 2, 3], [11,12,13], [21,22,23], [31,32,33]] b = [[41, 42, 43], [51,52,53], [61,62,63], [71,72,73]] summa_a_b = [[0,0,0], [0,0,0], [0,0,0], [0,0,0]] for i in range(len(a)): for j in range(len(a[0])): summa_a_b[i][j] = a[i][j] + b[i][j] print(summa_a_b) --OUTPUT&gt; [[42, 44, 46], [62, 64, 66], [82, 84, 86], [102, 104, 106]]<p>Заменим цикл генератором списка:</p>
107 a = [[1, 2, 3], [11,12,13], [21,22,23], [31,32,33]] b = [[41, 42, 43], [51,52,53], [61,62,63], [71,72,73]] summa_a_b = [[0,0,0], [0,0,0], [0,0,0], [0,0,0]] for i in range(len(a)): for j in range(len(a[0])): summa_a_b[i][j] = a[i][j] + b[i][j] print(summa_a_b) --OUTPUT&gt; [[42, 44, 46], [62, 64, 66], [82, 84, 86], [102, 104, 106]]<p>Заменим цикл генератором списка:</p>
108 a = [[1, 2, 3], [11,12,13], [21,22,23], [31,32,33]] b = [[41, 42, 43], [51,52,53], [61,62,63], [71,72,73]] summa_a_b = [[a[i][j] + b[i][j] for j in range(len(a[0]))] for i in range(len(a))] print(summa_a_b) --OUTPUT&gt; [[42, 44, 46], [62, 64, 66], [82, 84, 86], [102, 104, 106]]<p>После рефакторинга код стал короче.</p>
108 a = [[1, 2, 3], [11,12,13], [21,22,23], [31,32,33]] b = [[41, 42, 43], [51,52,53], [61,62,63], [71,72,73]] summa_a_b = [[a[i][j] + b[i][j] for j in range(len(a[0]))] for i in range(len(a))] print(summa_a_b) --OUTPUT&gt; [[42, 44, 46], [62, 64, 66], [82, 84, 86], [102, 104, 106]]<p>После рефакторинга код стал короче.</p>
109 <p>Почти в каждой программе приходится совершать операции над всеми элементами контейнерных типов данных: списков, словарей, кортежей.</p>
109 <p>Почти в каждой программе приходится совершать операции над всеми элементами контейнерных типов данных: списков, словарей, кортежей.</p>
110 <p>Иногда для этого создают переменную-счётчик и с её помощью перебирают элементы в цикле for, например:</p>
110 <p>Иногда для этого создают переменную-счётчик и с её помощью перебирают элементы в цикле for, например:</p>
111 spisok = [154,127,98,89,77,55,32,14] for i in range(len(spisok)): print(i + 1, spisok[i]) --OUTPUT&gt; 1 154 2 127 3 98 4 89 5 77 6 55 7 32 8 14<p>Получается, что программа перебирает не элементы списка, а значения переменной i, и каждый раз ищет нужный элемент. В сложных циклах это может привести к ошибкам. Кроме того, чтобы вывести на печать нумерованный список, в функции print() приходится прибавлять единицу к переменной i.</p>
111 spisok = [154,127,98,89,77,55,32,14] for i in range(len(spisok)): print(i + 1, spisok[i]) --OUTPUT&gt; 1 154 2 127 3 98 4 89 5 77 6 55 7 32 8 14<p>Получается, что программа перебирает не элементы списка, а значения переменной i, и каждый раз ищет нужный элемент. В сложных циклах это может привести к ошибкам. Кроме того, чтобы вывести на печать нумерованный список, в функции print() приходится прибавлять единицу к переменной i.</p>
112 <p>Можно улучшить код - использовать функцию enumerate(), которая перебирает элементы контейнера без промежуточной переменной. У этой функции два аргумента: переменная контейнерного типа (spisok) и начальное значение счёта (переменная i). Зададим второму аргументу значение 1, чтобы счёт начинался с единицы.</p>
112 <p>Можно улучшить код - использовать функцию enumerate(), которая перебирает элементы контейнера без промежуточной переменной. У этой функции два аргумента: переменная контейнерного типа (spisok) и начальное значение счёта (переменная i). Зададим второму аргументу значение 1, чтобы счёт начинался с единицы.</p>
113 <p>После рефакторинга код будет выглядеть так:</p>
113 <p>После рефакторинга код будет выглядеть так:</p>
114 spisok = [154,127,98,89,77] for i, spisok in enumerate(spisok, 1): print(i, spisok) --OUTPUT&gt; 1 154 2 127 3 98 4 89 5 77<p>Если переменная принимает разные значения в зависимости от того, выполняется или нет какое-то условие, то условный оператор if…else можно заменить тернарным выражением.</p>
114 spisok = [154,127,98,89,77] for i, spisok in enumerate(spisok, 1): print(i, spisok) --OUTPUT&gt; 1 154 2 127 3 98 4 89 5 77<p>Если переменная принимает разные значения в зависимости от того, выполняется или нет какое-то условие, то условный оператор if…else можно заменить тернарным выражением.</p>
115 <p>Рассмотрим пример:</p>
115 <p>Рассмотрим пример:</p>
116 def even_odd(number): if number % 2 == 0: state = "Even" else: state = "Odd" return state print(even_odd(128))<p>Заменим условие тернарным выражением:</p>
116 def even_odd(number): if number % 2 == 0: state = "Even" else: state = "Odd" return state print(even_odd(128))<p>Заменим условие тернарным выражением:</p>
117 def even_odd(number): return "Even" if number % 2 == 0 else "Odd"<p>Код стал короче и проще. Но у этого приёма есть ограничения - его стоит применять только к простым условным выражениям. В результате рефакторинга не должны появляться вложенные тернарные операторы, потому что их очень сложно читать.</p>
117 def even_odd(number): return "Even" if number % 2 == 0 else "Odd"<p>Код стал короче и проще. Но у этого приёма есть ограничения - его стоит применять только к простым условным выражениям. В результате рефакторинга не должны появляться вложенные тернарные операторы, потому что их очень сложно читать.</p>
118 <p>Например:</p>
118 <p>Например:</p>
119 def f_if_else(x,y): if (x==1): if(y==2): return 1 else: return 2 else: if(y==3): return 3 else: return 4<p>Если в функции выше заменить условное выражение тернарным оператором, то в результате получим:</p>
119 def f_if_else(x,y): if (x==1): if(y==2): return 1 else: return 2 else: if(y==3): return 3 else: return 4<p>Если в функции выше заменить условное выражение тернарным оператором, то в результате получим:</p>
120 def f_nested_if_else(x,y): return ((1) if (y == 2) else (2)) if (x == 1) else ((3) if (y == 3) else (4))<p>Код стал короче, но разобраться в нём теперь намного сложнее.</p>
120 def f_nested_if_else(x,y): return ((1) if (y == 2) else (2)) if (x == 1) else ((3) if (y == 3) else (4))<p>Код стал короче, но разобраться в нём теперь намного сложнее.</p>
121 <p>Присвоить значение сразу нескольким переменным в Python можно одной строкой.</p>
121 <p>Присвоить значение сразу нескольким переменным в Python можно одной строкой.</p>
122 <p>Пользоваться этой возможностью надо аккуратно - не усложнять понимание программы. Чтобы не запутаться, в одну строку объявляют переменные, которые связаны по смыслу.</p>
122 <p>Пользоваться этой возможностью надо аккуратно - не усложнять понимание программы. Чтобы не запутаться, в одну строку объявляют переменные, которые связаны по смыслу.</p>
123 <p><strong>Пример первый</strong></p>
123 <p><strong>Пример первый</strong></p>
124 name1 = 'Аня' name2 = 'Катя' name3 = 'Антон' name4 = 'Света'<p>Эти переменные можно объявить в одной строке. И код станет короче:</p>
124 name1 = 'Аня' name2 = 'Катя' name3 = 'Антон' name4 = 'Света'<p>Эти переменные можно объявить в одной строке. И код станет короче:</p>
125 name1,name2,name3,name4 = 'Аня', 'Катя', 'Антон', 'Света'<p><strong>Пример второй</strong></p>
125 name1,name2,name3,name4 = 'Аня', 'Катя', 'Антон', 'Света'<p><strong>Пример второй</strong></p>
126 <p>Иногда переменным нужно присвоить диапазон значений:</p>
126 <p>Иногда переменным нужно присвоить диапазон значений:</p>
127 one = 1 two = 2 three = 3 four = 4 print(' one is',one,'\n', 'two is', two, '\n', 'three is', three, '\n', 'four is', four) --OUTPUT&gt; one is 1 two is 2 three is 3 four is 4<p>В этом случае Python позволяет использовать множественное присваивание совместно с функцией range():</p>
127 one = 1 two = 2 three = 3 four = 4 print(' one is',one,'\n', 'two is', two, '\n', 'three is', three, '\n', 'four is', four) --OUTPUT&gt; one is 1 two is 2 three is 3 four is 4<p>В этом случае Python позволяет использовать множественное присваивание совместно с функцией range():</p>
128 one, two, three, four = range(1,5) print(' one is',one,'\n', 'two is', two, '\n', 'three is', three, '\n', 'four is', four)<p>Предположим, у нас есть два списка: первый - с именами друзей, а второй - это города, где они живут. Нужно объединить элементы списков в словарь вида "имя: город".</p>
128 one, two, three, four = range(1,5) print(' one is',one,'\n', 'two is', two, '\n', 'three is', three, '\n', 'four is', four)<p>Предположим, у нас есть два списка: первый - с именами друзей, а второй - это города, где они живут. Нужно объединить элементы списков в словарь вида "имя: город".</p>
129 <p>Это можно сделать с помощью цикла for:</p>
129 <p>Это можно сделать с помощью цикла for:</p>
130 friends = ["Катя", "Лена", "Даша", "Костя", "Дима"] cities = ["Москва", "Пенза", "Екатеринбург", "Минск"] friends_cities = {} for i in range(min(len(friends), len(cities))): friends_cities[friends[i]] = cities[i] print(friends_cities) --OUTPUT&gt; {'Катя': 'Москва', 'Лена': 'Пенза', 'Даша': 'Екатеринбург', 'Костя': 'Минск'}<p>Однако в Python встроена функция zip, которая делает то же самое - короче и проще.</p>
130 friends = ["Катя", "Лена", "Даша", "Костя", "Дима"] cities = ["Москва", "Пенза", "Екатеринбург", "Минск"] friends_cities = {} for i in range(min(len(friends), len(cities))): friends_cities[friends[i]] = cities[i] print(friends_cities) --OUTPUT&gt; {'Катя': 'Москва', 'Лена': 'Пенза', 'Даша': 'Екатеринбург', 'Костя': 'Минск'}<p>Однако в Python встроена функция zip, которая делает то же самое - короче и проще.</p>
131 <p>Её аргументами могут быть списки, кортежи, множества и словари. Функция zip возвращает итератор, объединяющий элементы из объектов-источников.</p>
131 <p>Её аргументами могут быть списки, кортежи, множества и словари. Функция zip возвращает итератор, объединяющий элементы из объектов-источников.</p>
132 <p>Например, передадим в zip аргументами строку, список и множество:</p>
132 <p>Например, передадим в zip аргументами строку, список и множество:</p>
133 arg1 = 'абвгдеж' arg2 = ['1','2','3','4','5'] arg3 = {'!','@','#','$','%','^'} zip_obj = zip(arg1, arg2, arg3) print(zip_obj) for i in zip_obj: print(i) --OUTPUT&gt; &lt;zip object at 0x000001D228F06BC0&gt; ('а', '1', '!') ('б', '2', '@') ('в', '3', '#') ('г', '4', '$') ('д', '5', '%')<p>В результате получим массив кортежей, каждый из которых содержит по одному элементу из каждого аргумента.</p>
133 arg1 = 'абвгдеж' arg2 = ['1','2','3','4','5'] arg3 = {'!','@','#','$','%','^'} zip_obj = zip(arg1, arg2, arg3) print(zip_obj) for i in zip_obj: print(i) --OUTPUT&gt; &lt;zip object at 0x000001D228F06BC0&gt; ('а', '1', '!') ('б', '2', '@') ('в', '3', '#') ('г', '4', '$') ('д', '5', '%')<p>В результате получим массив кортежей, каждый из которых содержит по одному элементу из каждого аргумента.</p>
134 <p>Теперь создадим словарь "имя: город" с использованием zip. Код будет выглядеть так:</p>
134 <p>Теперь создадим словарь "имя: город" с использованием zip. Код будет выглядеть так:</p>
135 friends = ["Катя", "Лена", "Даша", "Костя", "Дима"] cities = ["Москва", "Пенза", "Екатеринбург", "Минск"] friends_cities = dict(zip(friends, cities)) print(friends_cities) --OUTPUT&gt; {'Катя': 'Москва', 'Лена': 'Пенза', 'Даша': 'Екатеринбург', 'Костя': 'Минск'}<p>Функция zip работает до тех пор, пока не закончатся элементы в самом коротком из итерируемых объектов-аргументов.</p>
135 friends = ["Катя", "Лена", "Даша", "Костя", "Дима"] cities = ["Москва", "Пенза", "Екатеринбург", "Минск"] friends_cities = dict(zip(friends, cities)) print(friends_cities) --OUTPUT&gt; {'Катя': 'Москва', 'Лена': 'Пенза', 'Даша': 'Екатеринбург', 'Костя': 'Минск'}<p>Функция zip работает до тех пор, пока не закончатся элементы в самом коротком из итерируемых объектов-аргументов.</p>
136 <p>Если нужно ориентироваться на самый длинный список, то используют функцию zip_longest из модуля itertools:</p>
136 <p>Если нужно ориентироваться на самый длинный список, то используют функцию zip_longest из модуля itertools:</p>
137 from itertools import zip_longest friends = ["Катя", "Лена", "Даша", "Костя", "Дима"] cities = ["Москва", "Пенза", "Екатеринбург", "Минск"] friends_cities = dict(zip_longest(friends, cities)) print(friends_cities) --OUTPUT&gt; {'Катя': 'Москва', 'Лена': 'Пенза', 'Даша': 'Екатеринбург', 'Костя': 'Минск', 'Дима': None}<p>В среде разработки приложений<a>PyCharm</a>есть инструменты, которые помогают проводить рефакторинг. Они доступны через пункт<strong>Refactor</strong>главного меню. Научимся улучшать код с их помощью.</p>
137 from itertools import zip_longest friends = ["Катя", "Лена", "Даша", "Костя", "Дима"] cities = ["Москва", "Пенза", "Екатеринбург", "Минск"] friends_cities = dict(zip_longest(friends, cities)) print(friends_cities) --OUTPUT&gt; {'Катя': 'Москва', 'Лена': 'Пенза', 'Даша': 'Екатеринбург', 'Костя': 'Минск', 'Дима': None}<p>В среде разработки приложений<a>PyCharm</a>есть инструменты, которые помогают проводить рефакторинг. Они доступны через пункт<strong>Refactor</strong>главного меню. Научимся улучшать код с их помощью.</p>
138 <p>Открываем<strong>IDE</strong>и устанавливаем параметры рефакторинга в настройках редактора (<strong>File | Settings | Editor | Code Editing</strong>) в разделе<strong>Refactorings</strong>.</p>
138 <p>Открываем<strong>IDE</strong>и устанавливаем параметры рефакторинга в настройках редактора (<strong>File | Settings | Editor | Code Editing</strong>) в разделе<strong>Refactorings</strong>.</p>
139 <p>Если мы выберем режим<strong>In modal dialogs</strong>(во всплывающих окнах), то при использовании инструментов<strong>Extract/Introduce</strong>редактирование имён параметров, констант, полей и переменных будет происходить в открывающихся модальных окнах:</p>
139 <p>Если мы выберем режим<strong>In modal dialogs</strong>(во всплывающих окнах), то при использовании инструментов<strong>Extract/Introduce</strong>редактирование имён параметров, констант, полей и переменных будет происходить в открывающихся модальных окнах:</p>
140 <p>Если же мы предпочтём режим<strong>In the editor</strong>(в редакторе), то имена параметров, констант, полей и переменных будем редактировать прямо в редакторе:</p>
140 <p>Если же мы предпочтём режим<strong>In the editor</strong>(в редакторе), то имена параметров, констант, полей и переменных будем редактировать прямо в редакторе:</p>
141 <p>Для примера установим<strong>In modal dialogs</strong>.</p>
141 <p>Для примера установим<strong>In modal dialogs</strong>.</p>
142 <p>Теперь создадим в окне редактора новый проект (<strong>File | New Project</strong>) с именем<strong>refactorProject</strong>. Добавим в него новый файл (<strong>File | New | Python File</strong>), а назовём его, скажем,<strong>refactor.py</strong>.</p>
142 <p>Теперь создадим в окне редактора новый проект (<strong>File | New Project</strong>) с именем<strong>refactorProject</strong>. Добавим в него новый файл (<strong>File | New | Python File</strong>), а назовём его, скажем,<strong>refactor.py</strong>.</p>
143 <p>Разберём извлечение метода в PyCharm на одном из наших примеров:</p>
143 <p>Разберём извлечение метода в PyCharm на одном из наших примеров:</p>
144 while True : a1 = int(input( "Введите цену товара: ")) if a1 &lt; 0 : print ("Значение не должно быть отрицательным!") else : break while True : a2 = int(input("Введите количество товара: ")) if a2 &lt; 0 : print ("Значение не должно быть отрицательным!") else : break a3 = a1 * a2 print("Стоимость товара: ", a3)<p>Копируем этот код в окно редактора:</p>
144 while True : a1 = int(input( "Введите цену товара: ")) if a1 &lt; 0 : print ("Значение не должно быть отрицательным!") else : break while True : a2 = int(input("Введите количество товара: ")) if a2 &lt; 0 : print ("Значение не должно быть отрицательным!") else : break a3 = a1 * a2 print("Стоимость товара: ", a3)<p>Копируем этот код в окно редактора:</p>
145 <p>Выделим первый цикл while и используем инструмент<strong>Refactor | Extract/Introduce | Method</strong>из главного или контекстного меню (горячие клавиши<strong>Ctrl + Alt + M</strong>).</p>
145 <p>Выделим первый цикл while и используем инструмент<strong>Refactor | Extract/Introduce | Method</strong>из главного или контекстного меню (горячие клавиши<strong>Ctrl + Alt + M</strong>).</p>
146 <p>В нужное поле открывшегося окна вводим название функции - input_value ():</p>
146 <p>В нужное поле открывшегося окна вводим название функции - input_value ():</p>
147 <p>Чтобы добавить параметр функции, выделим подсказку "Введите стоимость товара: " и выберем в главном/контекстном меню инструмент<strong>Refactor | Introduce Parameter</strong><strong>(Ctrl + Alt + P)</strong>:</p>
147 <p>Чтобы добавить параметр функции, выделим подсказку "Введите стоимость товара: " и выберем в главном/контекстном меню инструмент<strong>Refactor | Introduce Parameter</strong><strong>(Ctrl + Alt + P)</strong>:</p>
148 <p>В появившемся модальном окне введём название параметра - prompt (в переводе с английского - "подсказка"):</p>
148 <p>В появившемся модальном окне введём название параметра - prompt (в переводе с английского - "подсказка"):</p>
149 <p>У нас получилось:</p>
149 <p>У нас получилось:</p>
150 def input_value(prompt): while True: a1 = int(input(prompt)) if a1 &lt; 0 : print ("Значение не должно быть отрицательным!") else : return a1<p>Заменим название переменной a1 на value с помощью инструмента рефакторинга "Переименование". Выделим a1 и выберем<strong>Refactor | Rename</strong>(<strong>Shift + F6</strong>):</p>
150 def input_value(prompt): while True: a1 = int(input(prompt)) if a1 &lt; 0 : print ("Значение не должно быть отрицательным!") else : return a1<p>Заменим название переменной a1 на value с помощью инструмента рефакторинга "Переименование". Выделим a1 и выберем<strong>Refactor | Rename</strong>(<strong>Shift + F6</strong>):</p>
151 <p>Дадим новым переменным осмысленные имена: price, quantity, cost.</p>
151 <p>Дадим новым переменным осмысленные имена: price, quantity, cost.</p>
152 <p>Теперь заменим дубли в нашем коде на вызовы функции с соответствующими значениями параметров. Исправленный код будет выглядеть так:</p>
152 <p>Теперь заменим дубли в нашем коде на вызовы функции с соответствующими значениями параметров. Исправленный код будет выглядеть так:</p>
153 def input_value(prompt): while True: value = int( input( prompt ) ) if value &lt; 0 : print ("Значение не должно быть отрицательным!") else : return value price = input_value("Введите цену товара: ") quantity = input_value("Введите количество товара: ") cost = price * quantity print("Стоимость товара: ", cost)<p>Как мы помним, переменной cost присваивается результат простого выражения (price * quantity) и больше с ней ничего не делается.</p>
153 def input_value(prompt): while True: value = int( input( prompt ) ) if value &lt; 0 : print ("Значение не должно быть отрицательным!") else : return value price = input_value("Введите цену товара: ") quantity = input_value("Введите количество товара: ") cost = price * quantity print("Стоимость товара: ", cost)<p>Как мы помним, переменной cost присваивается результат простого выражения (price * quantity) и больше с ней ничего не делается.</p>
154 <p>Поэтому нам можно от неё избавиться - заменить обращения к этой переменной выражением price * quantity. Сделаем это с помощью инструментов рефакторинга.</p>
154 <p>Поэтому нам можно от неё избавиться - заменить обращения к этой переменной выражением price * quantity. Сделаем это с помощью инструментов рефакторинга.</p>
155 <p>Выделим переменную cost и выберем в меню<strong>Refactor</strong>инструмент<strong>Inline</strong>("Встраивание") или вызовем его горячими клавишами<strong>Ctrl + Alt + N</strong>.</p>
155 <p>Выделим переменную cost и выберем в меню<strong>Refactor</strong>инструмент<strong>Inline</strong>("Встраивание") или вызовем его горячими клавишами<strong>Ctrl + Alt + N</strong>.</p>
156 <p><strong>PyCharm</strong>определит число вхождений и попросит подтвердить действие:</p>
156 <p><strong>PyCharm</strong>определит число вхождений и попросит подтвердить действие:</p>
157 <p>Нажимаем OK. Программа убирает выражение, в котором создаётся переменная cost, и везде подставляет вместо неё price * quantity:</p>
157 <p>Нажимаем OK. Программа убирает выражение, в котором создаётся переменная cost, и везде подставляет вместо неё price * quantity:</p>
158 def input_value(prompt): while True: value = int( input( prompt ) ) if value &lt; 0 : print ("Значение не должно быть отрицательным!") else : return value price = input_value ("Введите цену товара: ") quantity = input_value ("Введите количество товара: ") print ("Стоимость товара: ", price * quantity)<p>Чем объёмнее код, тем выгоднее применять инструменты рефакторинга. С ними уборка в коде ускоряется и ошибки сводятся к минимуму.</p>
158 def input_value(prompt): while True: value = int( input( prompt ) ) if value &lt; 0 : print ("Значение не должно быть отрицательным!") else : return value price = input_value ("Введите цену товара: ") quantity = input_value ("Введите количество товара: ") print ("Стоимость товара: ", price * quantity)<p>Чем объёмнее код, тем выгоднее применять инструменты рефакторинга. С ними уборка в коде ускоряется и ошибки сводятся к минимуму.</p>
159 <p>Мы рассмотрели лишь несколько приёмов рефакторинга - в Python их намного больше. Будучи быстрыми и несложными, вместе они здорово повышают качество проекта. Главное - проводить рефакторинг регулярно и не забывать затем тестировать приложение.</p>
159 <p>Мы рассмотрели лишь несколько приёмов рефакторинга - в Python их намного больше. Будучи быстрыми и несложными, вместе они здорово повышают качество проекта. Главное - проводить рефакторинг регулярно и не забывать затем тестировать приложение.</p>
160 <a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>
160 <a><b>Бесплатный курс по Python ➞</b>Мини-курс для новичков и для опытных кодеров. 4 крутых проекта в портфолио, живое общение со спикером. Кликните и узнайте, чему можно научиться на курсе. Смотреть программу</a>