Объектно-ориентированное программирование (ООП) в Питоне




 

ООП:

—инкапсуляция (скрываем внутреннее представление, ограничивая пользователя каким-то внешним интерфейсом)

—полиморфизм

—наследование

 

объект (класс) содержит данные и функции/поведение.

 

по сути, объект является моделью некоторой сущности (в т.ч., например, физической — например, велосипеда).

 

предметная область — грубо говоря, «контекст» (ср. «фрейм»), в котором функционирует программа (e.g. продажа велосипедов) — он предопределяет типы объектов/данных и типы требуемых функций/поведения; предметная область включает сущности и процессы.

 

class Bike:

def __init__ (self, color, frame_material):

self. color = color

self. frame_material = frame_material

 

def brake(self):

print("The {} {} bike is breaking".format(self.color, self.frame_material))

 

red_wooden_bike = Bike("red", "wood")

green_steel_bike = Bike("green", "steel")

 

red_wooden_bike .brake()

green_steel_bike .brake()

 

 

инкапсуляция — сокрытие данных в оболочке класса. снаружи ко всем данным объекта мы можем получить доступ только через его интерфейс (~набор функций-методов).

 

напрямую можно тоже, язык позволяет, — но это считается неправильным:

print("Color = {}".format(red_wooden_bike.color))

 

так уже немного лучше:

def get_color(self):

return self.color

print("Color = {}".format(red_wooden_bike.get_color()))

 

но ещё лучше вообще реализовывать нужное поведение прямо внутри класса везде, где это возможно (т.е. в данном случае — создать внутреннюю функцию типа “show_color”).

 

 

небольшой хак: плейсхолдер pass — когда нам что-то нужно написать в коде, но мы пока не написали — чтобы код продолжал работать:)

ср.:

class Frame: pass

плюс pass бывает нужен и в готовом коде — если мы намеренно создаём пустышку, которая потом где-то в коде переопределяется.

 

 

инвариант — строго определённое, согласованное состояние

в хорошем ООП у класса должно быть инвариантное состояние.

аналогия: робот, которого нужно переместить из точки A в точку B — мы не руками его перетаскиваем, а передаём ему набор команд, который приводит в итоге к его перемещению в нужную точку.

т.е. по возможности всё делать через методы класса (интерфейс), а не через прямые отсылки к его внутренним переменным.

 

можно визуализировать сложные структуры объектов/классов с помощью UML, Rational Rose, etc.

 

class Person():

species = 'Human'

 

— это переменная «по умолчанию»

 

 

в Питоне классы (абстрактные, без конкретных экземпляров) сами по себе тоже являются изменяемыми объектами, и их можно менять во время исполнения кода!!! т.е. добавлять новые переменные / менять переменные «по умолчанию», даже добавлять и менять функции!

 

class Square():

side = 8

 

def area(self):

return self.side ** 2

 

sq = Square()

print("Square = {}".format(sq.area()))

print("Square = {}".format(Square.area(sq)))

# print("Square = {}".format(Square.area())) # не должно работать

 

объявлять функции внутри класса без аргумента self можно, но только как статические (и не понятно, зачем), и с вызовом собственных переменных через название класса:

def perimeter ()

return Square. side * 4

 

но в норме всегда пишется self при определении функции внутри класса.

 

вообще на самом деле при стандартном виде вызова — “sq.area()” — self добавляется автоматически, т.е. эта запись на самом деле эквивалентна “Square.area(sq)”

 

даже конструктор вызывается на самом деле так же. т.е. обычная краткая запись:

sq = Square()

— равносильна на самом деле:

Square.__init__(sq)

 

конструктор класса — это метод __init__()

 

вообще внутри самих создаваемых экземпляров класса по умолчанию создаётся только то, что создаётся внутри __init__(), остальное остаётся в общем объекте класса, и вызывается оттуда.

 

 

==============

Февраля

 

Пользовательский интерфейс — будет на следующем занятии.

 

взял доклад про PyQt!!

общий тьюториал, как установить, как окошко отобразить, примеры небольшие.

если что — писать Антону.

см. wiki.python.org/moin/GuiProgramming/

 

Объектно-ориентированное программирование (ООП) в Питоне, ч. 2

 

Наследование (inheritance)

 

class Base:

def __init__(self, value_1, value_2):

self._value_1 = value_1 # конвенция: нижнее подчёркивание (_) в начале имени переменной показывает, что это внутренние данные, которые лучше не трогать извне

self._value_2 = value_2

 

def calculate_sum(self):

return self._value_1 + self._value_2

 

class Derived (Base): pass

 

test_derived = Derived(12, 12)

 

print(test_derived.calculate_sum())

 

можно теперь что-то поменять, например, сделать создание класса с дважды продублированным аргументом:

 

class Base:

def __init__(self, value_1, value_2):

self._value_1 = value_1

self._value_2 = value_2

 

def calculate_sum(self):

return self._value_1 + self._value_2

 

class Derived(Base):

def __init__(self, single_value):



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2019-06-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: