Парадигмы программирования¶
В отличии от Fortran или С которые поддерживают только парадигму процедурного программирования Python позволяет писать код также в объектно-ориентированном и функциональном стилях.
Объектно-ориентированное программировние (ООП)¶
ООП основанное на использовании специальных типов - классов, которые объеденяют данные и способы работы с ними.
В языке Pascal вы можете создать переменную типа string и например передать её в функцию ToUpperCase:
variable := 'AaBb'
toUpperCase(variable)
// Теперь variable содержит строку 'AABB'
Но приведение к верхнему регистру это операция характерная для строк, бессмысленно пытаться приводить целое число к нему. Поэтому ООП предлагает превратить функцию ToUpperCase в метод класса, иначе говоря в функцию-член класса. Рассмотрим пример:
a = "AaBb"
type(a)
В переменную a
мы сохранили строку "AaBb", которая явлется экземпляром (объектом) класса str
. Теперь мы можем вызвать у переменной a
один из методов класса str
.
a.upper()
# Метод может принимать аргументы (на самом деле любой метод принимает как минимум один аргумент подробнее [здесь]())
# Например посчитаем сколько раз буква A входит в строку
a.count('A')
# Возвращаясь к форматированию строк,
# то наилучшим способом будет использования метода format
"My name is {}, my age is {:d} and my temperature is {:.1f} degree.".format("Mikahil", 24, 36.6)
a = 0.5 # Числа тоже имеют методы
a.as_integer_ratio() # Представляет вещественное число как отношение целых
dir(a) # Позволяет узнать методы, определенные у объекта,
# методы начинающиеся с двойного подчеркивая --- служебные и обычно явно не вызываются
In-place и Out-of-place операции¶
Операции проводимые in place производятся непосредвенно с объектом вызвашим эту операцию, а out of place создают новый объект. Сравним два примера.
data = [1, 3, 2]
data.sort()
print("Список data изменился: {}".format(data))
data = [ 1,3,2]
res = sorted(data)
print("Список data не изменился: {}".format(data))
print("Список res содержит результат сортировки: {}".format(res))
В первом примере вызов метода sort отсортировал список data, во втором примере функция sorted создала новый отсртированный список оставив порядок элементов в data неизменным
Пользовательские типы (Дополнительный материал)¶
Однако мы можем использовать не только классы изначально сушествующие в языке, но и создавать свои!
class VelocityVector2D:
"""
Класс описывающий двумерный вектор скорости
"""
units = "м/c"
def __init__(self, x, y):
"""
Значение переменных x,y считается данным в м\с
"""
self.x = x
self.y = y
def module(self, system_of_units = "SI"):
"""
Модуль вектора скорости
Аргумент system_of_units может принимать значения "SI" и "SGS"
"""
module = (self.x**2 + self.y**2)**0.5
if system_of_units=="SI":
return module
elif system_of_units=="SGS":
return module*10 # Перевели из СИ в СГС
else:
raise Exception('Незнакомая система единиц')
def __add__(self, another_vector):
"""
Позволяет складывать два вектора с помощью оператора +
"""
return VelocityVector2D(self.x + another_vector.x, self.y + another_vector.y)
def __repr__(self):
"""
Генериует строковой представление для нашего класса
Например, мы теперь можем сделать:
print(VelocityVector2D(3,4))
"""
return "Vx = {0} {2}, Vy = {1} {2}".format(self.x, self.y , self.units)
v1 = VelocityVector2D(3,4)
v1.x
v1.module()
print("Модуль скорости равен {}".format(v1.module()))
v_rel = v1 + VelocityVector2D(-3,-4)
print(v_rel)
Функциональное программирование (ФП)¶
Одной из основ ФП является передача функции в качестве аргумента для другой функции. Для пример реализуем функцию которая будет вычислять интеграл от произвольной функции.
def riman_integral(function, left_boundary = 0, rigth_boundary = 1, number_points = 200):
"""
Вычисляем интеграл методом прямоугольников.
Это определенно не самый лучший способ численного интегрирования,
но самый простой и для функций без особенностей дает приемлимую точность.
Отметим что реализация данной функции основанно на чистом Python
и поэтому не является оптимальной по производительности.
О высокопроизводительных вычислениях смотри раздел Numpy и Scipy
"""
a, b = left_boundary, rigth_boundary
dx = (b - a) / (number_points - 1) # Интервалов на один меньше чем точек
res = function(a)
for i in range(1, number_points - 1):
res += function(a + i*dx)
res += function(b)
return res*dx
from math import cos, pi
# В качестве аргумента мы передаем функцию cos от которой вычисляем интеграл
riman_integral(cos, 0, pi/2) # Вопрос на засыпку, верен ли результат?
Анонимные функции (дополнительный материал)¶
Другим пример функционального стиля, является использование аномнимных функций. Анонимные функции могут содержать лишь одно выражение. Создаются с помощью инструкции lambda
. Рассмотрим на примере такой задачи: дан набор скоростей, нужно получить набор отсортированный по модулю скорости.
data = [VelocityVector2D(0,0),
VelocityVector2D(1,1),
VelocityVector2D(0.1,0.5)]
print("Текущий порядок")
for element in data:
print(element)
result = sorted(data, # Входные данные
key = lambda velocity : velocity.module() # Функция принимающая в качестве аргумента элемент из data
# и определяющая порядок сортировки
)
print("Порядок после сортировки")
for element in result:
print(element)
# Анонимная функция так же может иметь несколько аргументов
print((lambda x, y: x * y)(1, 2))