Главная страница

Сам_себе_программист._Как_научиться_программировать_и_устроиться. Guide to Programming Professionally


Скачать 3.94 Mb.
НазваниеGuide to Programming Professionally
Дата25.02.2023
Размер3.94 Mb.
Формат файлаpdf
Имя файлаСам_себе_программист._Как_научиться_программировать_и_устроиться.pdf
ТипGuide
#954463
страница8 из 15
1   ...   4   5   6   7   8   9   10   11   ...   15

Глава 11. Дополнительная информация
Практика не приводит к совершенству. Практика приводит к образованию миелина, а миелин приводит к совершенству.
Дэниел Койл
Если это ваша первая книга по программированию, рекомендую потратить вре- мя на поиск дополнительной информации, прежде чем переходить к следующе- му разделу. Ниже приведены некоторые ресурсы для исследования — на них так- же можно получить советы, если у вас возникли трудности.

Для прочтения
1. softwareengineering.stackexchange.com/questions/44177/what-is-the-
single-most-effective-thing-you-did-to-improve-your-programming-skil
Другие ресурсы
Документация к Python — docs.python.org/3/.
Краткий справочник Python — cloud.github.com/downloads/kroger/python-
quick-ref/python-quick-ref.pdf.
Получение помощи
Если вы у вас возникли трудности, у меня есть для вас несколько предло- жений. В первую очередь, опубликуйте свой вопрос в группе Self-Taught
Programmers в социальной сети Facebook по адресу www.facebook.com/groups/
selftaughtprogrammers. Это сообщество дружелюбных и целеустремленных программистов, которые помогут найти ответ на любой ваш вопрос.
Я также советую посетить ресурс www.stackoverflow.com, на котором можно публиковать вопросы по программированию и получать ответы участников со- общества.
Для меня важным уроком было научиться рассчитывать на помощь других людей. Попытки в чем-то разобраться — это основная часть учебного процесса, но на определенном этапе они могут стать контрпродуктивными. В прошлом, когда я работал над проектами, мои усилия были ниже точки продуктивности.
Если подобное случается сегодня, и я не нахожу ответ быстро, то публикую во- прос онлайн. Каждый раз, когда я задавал вопрос в Интернете, на него обяза- тельно отвечали. В этой связи я не могу в полной мере описать то, насколько дружелюбным и стремящимся помочь является программистское сообщество.

108
Глава 12. Парадигмы программирования
Существуют лишь два вида языков программирования:
те, которые постоянно ругают, и те, которыми никто не пользуется.
Бьерн Страуструп
Парадигма программирования — это стиль программирования. Существует множество различных парадигм программирования. Для того чтобы програм- мировать профессионально, вам нужно изучить парадигмы либо объектно-ори- ентированного, либо функционального программирования. В этой главе вы узнаете о процедурном, функциональном и объектно-ориентированном про- граммировании, а больше всего внимания будет уделено объектно-ориентиро- ванному программированию.
Состояние
Одним из фундаментальных различий между разными парадигмами программи- рования является управление состоянием. Состояние — это значение перемен- ных в программе при ее работе. Глобальное состояние — значение глобальных переменных в программе при ее работе.
Процедурное программирование
В части I вы программировали, используя парадигму процедурного програм-
мирования — стиль программирования, в котором пишется последовательность шагов по направлению к решению, и каждый шаг изменяет состояние програм- мы. В процедурном программировании вы пишете код, чтобы «сделать это, за- тем то».
ЧАСТЬ II
Введение
в объектно-ориентированное
программирование

109
Введение в объектно-ориентированное программирование
Python_ex233.py
1 x
= 2 2
y
= 4 3
z
= 8 4
xyz
= x + y + z
5
xyz
>> 14
Каждая строка кода в этом примере изменяет состояние программы. Снача- ла вы определяете x, затем y, затем z. В конце вы определяете значение xyz.
Когда вы используете процедурное программирование, то сохраняете дан- ные в глобальных переменных и управляете ими при помощи функций.
Python_ex234.py
1
rock
= []
2
country
= []
3
def collect_songs():
4
song
= "| &  W."
5
ask
= "

  ( )   ( ).    G  "
6
while
True
:
7
genre
= input(ask)
8
if genre == "":
9
break
10
if genre == "":
11
rk
= input(song)
12
rock.append(rk)
13
elif genre ==(""):
14
cy
= input(song)
15
country.append(cy)
16
else:
17
print("$ .")
18
print(rock)
19
print(country)
20
collect_songs()
>>   ( )   ( ).    G 

110
Часть II
Процедурное программирование подходит для написания небольших программ вроде этой, однако из-за того, что все состояния программы сохра- няются в глобальных переменных, когда код становится больше, появляются проблемы. Проблема с использованием глобальных переменных заключает- ся в том, что они вызывают непредвиденные ошибки. Когда код вашей про- граммы увеличивается в размере, вы используете глобальные переменные в большом количестве функций, и невозможно отследить все места, в которых глобальная переменная изменяется. Например, функция может изменить зна- чение глобальной переменной, а позже в программе другая функция может изменить ту же глобальную переменную, потому что программист, написав- ший вторую функцию, забыл, что глобальная переменная уже была изменена первой функцией. Подобные ситуации возникают довольно часто, искажая код программы.
По мере того, как ваша программа усложняется, количество глобальных пе- ременных в ней возрастает. Когда это возрастание совмещается с увеличением числа функций, необходимых программе для обработки новой функциональ- ности, каждая из которых изменяет глобальные переменные, код вашей про- граммы быстро становится непригодным для обслуживания. Более того, этот подход к программированию опирается на побочные эффекты. Побочный эффект — это изменение состояния глобальной переменной. При процедур- ном программировании вы будете часто сталкиваться с непреднамеренными побочными эффектами, такими как случайное двукратное увеличение пере- менной.
Эта проблема привела к развитию парадигм объектно-ориентированного и функционального программирования, и эти парадигмы используют разные под- ходы к ее решению.
Функциональное программирование
Функциональное программирование происходит от лямбда-исчисления — наименьшего в мире универсального языка программирования (созданного ма- тематиком Алонзо Черчем). Функциональное программирование решает про- блемы процедурного программирования с помощью устранения глобального состояния. Функциональный программист полагается на функции, которые не используют и не изменяют глобальное состояние; единственное используемое ими состояние — параметры, которые вы передаете в функцию. Результат, воз- вращаемый функцией, обычно передается в другую функцию. Таким образом, выполняя передачу из функции в функцию, функциональный программист из- бегает глобального состояния. Отказ от глобального состояния избавляет от побочных эффектов и сопутствующих им проблем.
Программист из Великобритании, Мэри Роуз Кук, дает функционально- му программированию такое определение: «Функциональный код отличается одним свойством: отсутствием побочных эффектов. Он не полагается на дан- ные вне текущей функции, и не меняет данные, находящиеся вне функции»
7
Свое определение она продолжает примером функции, имеющей побочные эффекты.
7
maryrosecook.com/blog/post/a-practical-introduction-to-functional-programming

111
Введение в объектно-ориентированное программирование
Python_ex235.py
1
a
= 0 2
def increment():
3
global a
4
a += 1
И примером функции без побочных эффектов.
Python_ex236.py
1
def increment(a):
2
return a + 1
У первой функции есть побочные эффекты, поскольку она полагается на дан- ные за ее пределами и изменяет данные вне текущей функции, увеличивая значе- ние глобальной переменной. У второй функции нет побочных эффектов, так как она не полагается на данные за ее пределами и не изменяет эти данные.
Преимущество функционального программирования заключается в том, что оно устраняет целую категорию ошибок, вызванных глобальным состоянием (в функциональном программировании нет глобального состояния). Его недоста- ток заключается в том, что некоторые проблемы легче осмыслить при помощи состояния. К примеру, проектирование пользовательского интерфейса с гло- бальным состоянием легче концептуализировать, чем интерфейс без него. Если вы хотите написать программу, где будет кнопка, нажатие которой переключает режим изображения между видимым и скрытым, такую кнопку проще создать в программе с глобальным состоянием. Можно создать глобальную переменную, принимающую значение True или False и в зависимости от своего те кущего со- стояния скрывающую или показывающую это изображение. Без глобального со- стояния создать такую кнопку сложнее.
Объектно-ориентированное программирование
Парадигма объектно-ориентированного программирования также решает проблемы, возникающие в процедурном программировании путем устранения глобального состояния, но здесь состояние сохраняется не в функциях а в объ- ектах. В объектно-ориентированном программировании классы определяют на- бор объектов, которые могут взаимодействовать между собой. Классы являются механизмом, позволяющим программисту классифицировать и сгруппировы- вать похожие объекты. Представьте пакет апельсинов. Каждый апельсин — это объект. Все апельсины обладают схожими свойствами, такими как цвет и вес, но значения этих свойств разные у каждого апельсина. Вы можете использовать класс, чтобы смоделировать апельсины и создать объекты апельсинов с разны- ми значениями. Например, можно определить класс , позволяющий создать объ- ект апельсина темного цвета, весящего 300 грамм, и объект светлого апельсина весом 350 грамм.
Каждый объект — это экземпляр класса. Если вы определите класс Orange и создадите два объекта Orange, каждый из них будет экземпляром класса Orange,

112
Часть II
и у них будет одинаковый тип данных — Orange. Термины «объект» и «экзем- пляр» взаимозаменяемы. При определении класса экземпляры класса будут по- хожими — они все будут иметь свойства, определенные в их классе, как цвет или вес для класса, представляющего апельсин, — но свойства каждого экземпляра будут иметь разные значения.
В Python класс является составной инструкцией с заголовком и телом . Класс определяется при помощи синтаксиса class : , где — это имя класса,  — определяемое вами тело класса. По соглашению , имена классов в Python всегда начинаются с прописной буквы и записываются в горбатом ре- гистре, то есть при наличии в имени класса больше одного слова первые буквы всех слов нужно сделать прописными (LikeThis), а не добавлять между слова- ми нижние подчеркивания , как с именами функций. Тело в классе может быть простой или составной инструкцией, называемой методом. Методы напомина- ют функции, только их определяют внутри класса и вызывают в объекте, создан- ном классом (как в части I, когда вы вызывали методы вроде "hello".upper() в строках). Имена методов, как и функций, должны указываться строчными бук- вами, а слова должны быть отделены нижними подчеркиваниями.
Методы определяются с помощью такого же синтаксиса , что и функции, с двумя отличиями: нужно определить метод как тело в классе, и он должен при- нимать, по меньшей мере, один параметр (за исключением особых случаев). По соглашению, первый параметр метода всегда называется self
. При создании метода вы должны всегда определять хотя бы один параметр, поскольку, когда метод вызывается в объекте, Python автоматически передает вызвавший мето д объект в этот метод в качестве параметра.
Python_ex237.py
1
class Orange:
2
def __init__(self):
3
print("% B !")
Вы можете использовать параметр self, чтобы определить переменную
экземпляра — переменную, принадлежащую объекту. Если вы создадите несколько объектов, у них всех будут разные значения переменных экземпляра. Перемен- ные экземпляра объявляются с помощью синтаксиса self. _   =
 _  . Обычно переменные экземпляра определяются вну- три специального метода __init__ (от англ. слова initialize — инициализиро- вать), который вызывается Python при создании объекта.
Ниже приведен пример класса, представляющего апельсин.
Python_ex238.py
1
class Orange:
2
def __init__(self, w, c):
3
self.weight = w
4
self.color = c
5
print("% B !")

113
Введение в объектно-ориентированное программирование
Код в __init__ выполняется при создании объекта Orange (чего в этом примере не происходит) и создает две переменные экземпляра: weight и color
. Их можно использовать как обычные переменные, в любом методе ва- шего класса. Когда вы создаете объект Orange, код в __init__ выводит стро- ку % B !. Любой метод, окруженный двойными нижними подчеркиваниями
(как __init__), является магическим методом, который Python использует для особых целей, таких как создание объекта.
Вы можете создать новый объект Orange с помощью того же синтаксиса, что вы использовали для вызова функции — _  (   ) — толь- ко замените _  именем класса, который вы хотите использовать для создания объекта, а слово     — параметрами, которые принимает __
init__
. Не нужно передавать self
, Python сделает это автоматически. Созда- ние нового объекта называется созданием экземпляра класса .
Python_ex239.py
1
class Orange:
2
def __init__(
self
, w, c):
3
self
.weight = w
4
self
.color = c
5
print("% B !")
6
or1
= Orange(10, "   ")
7
print(or1)
>> % B !
После определения класса, вы создаете экземпляр класса Orange при помо- щи кода Orange(10, "   "), в этом случае выводится строка
% B !
. Затем вы выводите сам объект Orange, Python сообщает вам, что это объект Orange, и выдает его местонахождение в памяти (в вашем случае, распо- ложение в памяти не будет совпадать с указанным в данном примере).
Как только вы создали объект, можно получить значение его переменных эк- земпляра с помощью синтаксиса _ . _  
Python_ex240.py
1
class Orange:
2
def __init__(
self
, w, c):
3
self
.weight = w
4
self
.color = c
5
print("% B !")
6
or1 = Orange(10, "   ")
7
print(or1.weight)
8
print(or1.color)

114
Часть II
>> % B !
>> 10
>>   
Значение переменной экземпляра можно изменить с помощью синтаксиса
_ . _   = _ .
Python_ex241.py
1
class Orange:
2
def __init__(
self
, w, c):
3
self
.weight
= w
4
self
.color
= c
5
print("% B !")
6
or1 = Orange(10, "   ")
7
or1.weight = 100 8
or1.color = "  "
9
print(or1.weight)
10
print(or1.color)
>> % B !
>> 100
>>  
Несмотря на то что значения переменных экземпляра color и weight были "   "
и 10, соответственно, вы смогли их изменить, присвоив им значения "  " и 100.
Используя класс Orange, вы можете создать множество апельсинов.
Python_ex242.py
1
class Orange:
2
def __init__(
self
, w, c):
3
self
.weight
= w
4
self
.color
= c
5
print("% B !")
6
or1
= Orange(4, "  ")
7
or2
= Orange(8, "   ")
8
or3
= Orange(14, "&  ")
>> % B !
>> % B !
>> % B !

115
Введение в объектно-ориентированное программирование
Апельсин не определяется одними только физическими свойствами вроде цвета и веса. Апельсины делают разные вещи — например, гниют — и вы можете смоделировать их с помощью методов. Ниже показано, как можно наделить объ- ект Orange возможностью «гнить».
Python_ex243.py
1
class Orange():
2
def __init__(
self
, w, c):
3
"""    G"""
4
self
.weight
= w
5
self
.color
= c
6
self
.mold
= 0 7
print("% B !")
8
def rot(
self
, days, temp):
9
self
.mold
= days * temp
10
orange
= Orange(6, "  ")
11
print(orange.mold)
12
orange.rot(10, 33)
13
print(orange.mold)
>> % B !
>> 0
>> 330
Метод rot принимает два параметра: число дней, прошедших с тех пор как кто-то сорвал апельсин, и среднюю температуру за этот период. Когда вы вы- зываете метод, он использует формулу для увеличения переменной экземпляра mold
— это работает, поскольку вы можете изменять значение любой перемен- ной экземпляра внутри любого метода. Теперь апельсин может гнить.
В классе можно определять множество методов. Ниже приведен пример по- строения модели прямоугольника при помощи метода для расчета его площади и другого метода для изменения его размера.
Python_ex244.py
1
class Rectangle():
2
def __init__(
self
, w, l):
3
self
.width = w
4
self
.len = l
5
def area(
self
):
6
return self
.width * self
.len

116
Часть II
7
def change_size(
self
, w, l):
8
self
.width = w
9
self
.len = l
10
rectangle = Rectangle(10, 20)
11
print(rectangle.area())
12
rectangle.change_size(20, 40)
13
print(rectangle.area())
>> 200
>> 800
В этом примере объекты Rectangle имеют две переменные экземпляра: len и width. Метод area возвращает площадь объекта Rectangle, перемножая между собой переменные экземпляра, а метод change_size изменяет перемен- ные, присваивая им числа, которые передаются в качестве параметров.
У объектно-ориентированного программирования есть несколько преиму- ществ. Эта парадигма способствует повторному использованию кода и вслед- ствие этого сокращает количество времени, необходимое на разработку и об- служивание кода. Проблемы разбиваются на множество фрагментов, благодаря чему код становится легче поддерживать. Недостатком объектно-ориентирован- ного программирования можно считать то, что создание программ требует боль- ших усилий, поскольку их разработка включает огромный объем планирования.
Словарь терминов
Глобальное состояние: значение глобальных переменных в программе при ее работе.
Классы: механизм, позволяющий программисту классифицировать и сгруппи- ровывать похожие объекты.
Магический метод: метод, который Python использует в разных ситуациях, на- пример, при создании объекта.
Методы: тело в классах. Методы похожи на функции, только их определяют вну- три класса и вызывают только в объекте, созданном классом.
Объектно-ориентированное программирование: парадигма программирова- ния, где вы определяете объекты, которые взаимодействуют друг с другом.
Парадигма программирования: стиль программирования.
Переменные экземпляра: переменные, которые принадлежат объекту.
Побочный эффект: изменение состояния глобальной переменной.
Процедурное программирование: стиль программирования, в котором пишет- ся последовательность шагов по направлению к решению, и каждый шаг изменя- ет состояние программы.
Создание экземпляра класса: создание нового объекта при помощи класса.
Состояние: это значение переменных в программе во время ее работы.
Функциональное программирование: решает проблемы процедурного про- граммирования с помощью устранения глобального состояния, передавая его от функции к функции.

117
Введение в объектно-ориентированное программирование
Экземпляр: каждый объект это экземпляр класса. Каждый экземпляр класса имеет тот же тип, что и все остальные экземпляры этого класса.
Практикум
1. Определите класс
Apple с четырьмя переменными экземпляра, представля- ющими четыре свойства яблока.
2. Создайте класс
Circle с методом area, подсчитывающим и возвращающим площадь круга. Затем создайте объект Circle, вызовите в нем метод area и выведите результат. Воспользуйтесь функцией pi из встроенного в Python модуля math.
3. Создайте класс
Triangle с методом area, подсчитывающим и возвращаю- щим площадь треугольника. Затем создайте объект Triangle, вызовите в нем area и выведите результат.
4. Создайте класс Hexagon с методом calculate_perimeter, подсчитыва- ющим и возвращающим периметр шестиугольника. Затем создайте объект
Hexagon
, вызовите в нем calculate_perimeter и выведите результат.
Решения: chall_1.py — chall_4.py.
1   ...   4   5   6   7   8   9   10   11   ...   15


написать администратору сайта