Объектно-ориентированное программирование (ООП) - это технология в которой объекты создаются с помощью классов. Класс описывает свойства объекта или объектов, создаваемых на его основе. Объект - это экземпляр класса.
Классы создаются с помощью ключевого слова class. Например:
class animal:
pass
class flora(object):
pass
class dog(animal):
pass
Лист. 1. Создание классов
Классы animal и flora созданы на основе базового класса object, класс dog создан на основе класса animal. Класс dog наследует свойства класса animal, и является его наследником. Класс animal является суперклассом по отношению к классу dog.
from tkinter import * # графическая библиотека
class Btn(Button):
pass
Btn(width=3, height=2, font=('times', 24, 'bold'),
text="Yes").pack(expand=YES, fill=BOTH, side=LEFT)
mainloop() # главный цикл программы
Лист. 2. Класс Btn наследник класса Button из библиотеки tkinter.
Рис. 1. Кнопка типа (класса) Btn создана конструктором суперкласса Button.
Кнопка на рисунке 1 создана программой листинг 1. Создание кнопки как объекта (экземпляра класса) в программе листинг 1 произошло когда мы использовали имя класса Btn как функцию, с круглыми скобками Btn(). Параметры, перечисленные в круглых скобках при вызове конструктора класса Btn описаны в классе Button в библиотеке tkinter. Здесь мы их не рассматриваем.
К объекту класса Btn в программе листинг 1 применяется (вызывается) метод (встроенная функция) pack(). Функция pack(), так же, как и упомянутые выше параметры класса Button, является свойством класса Button. Методы объектов вызываются с использованием составного имени через точку:
Имя_объекта.имя_метода(параметры)
Имя объекта (точнее ссылка на объект) класса Btn в программе листинг 1 возвращается в то место где был вызван конструктор Btn() с параметрами.
На самом деле, пока в программе листинг 1 в классе Btn не объявлен свой конструктор объектов - функция __init__, при создании экземпляров класса Btn используется метод __init__() суперкласса Button.
Создавая пользовательский класс Btn, мы планируем снабдить его дополнительными свойствами. Нет большого смысла в новом классе, который полностью повторяет свойства суперкласса. В программу листинг 2 в класс Btn мы добавим свой конструктор __init__(). Заметим, что у функции __init__() должен быть, как минимум, один обязательный параметр self. И любые другие методы класса, так же как и метод __init__(), должны иметь в качестве первого передаваемого параметра параметр self. Параметр self является ссылкой на создаваемый объект (экземпляр класса). Self программистом внутри класса не определяется, а только используется. При вызове методов объекта параметр self не указывают.
from tkinter import * # графическая библиотека
class Btn(Button):
def __init__(self, color, *args, **kwards): # конструктор объекта класса
print(args, kwards)
super().__init__(*args, **kwards) # вызов конструктора суперкласса
self.config(bg=color)
self.pack(expand=YES, fill=BOTH, side=LEFT)
tk = Tk() # главное окно программы
# создание объекта типа Btn
Btn('pink', tk, width=3, height=2,
text="Yes", font=('times', 24, 'bold'))
mainloop() # главный цикл программы
Лист. 3. Пример использования параметров *args **kwargs для передачи аргументов в функцию.
(<tkinter.Tk object .>,) {'width': 3, 'height': 2, 'text': 'Yes', 'font': ('times', 24, 'bold')}
Лист. 4. Вывод из программы в командную строку.
В программе листинг 3 *args позволяет передать в параметр args позиционные аргументы, представляемые в виде кортежа, а **kwargs передаёт в kwargs именованные аргументы, представленные в виде словаря.
Рис. 2. Результат работы программы листинг 8.
Цвет кнопки в конструктор класса Btn передан как параметр 'pink'.
Игровое поле
Напишем на Python с графической библиотекой tkinter программу (заготовку) шаблон для логических игр c прямоугольным полем в клетку. В качестве клеток на поле будем использовать кнопки.
Перечислим примеры логических игр на поле в клетку:
- Шашки,
- Шахматы,
- Го,
- Уголки,
- Крестики нолики,
- Линии (Lines98),
- Пазлы - головоломки:
- Пятнашки,
- Что ест уж,
- Чайный сервиз,
- Flip-Flop,
- Memory,
- Сапёр,
- Пег,
- Игры с цифрами:
- 2048
- Судоку
- Number Match
- Трубопровод...
Для создания компьютерных игр в клетку, где в качестве клеток будут использоваться кнопки напишем программу на языке программирования Python с использованием графической библиотеки tkinter.
from tkinter import * # графическая библиотека
column = 3 # столбцы
class Btn(Button):
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards)
self.pack(expand=YES, fill=BOTH, side=LEFT)
Btn(width=3, height=2, font=('times', 24, 'bold'))
mainloop() # главный цикл программы
Лист. 5. Одна кнопка.
Рис. 3. Кнопка создана программой лист. 5.
from tkinter import * # графическая библиотека
column = 3 # столбцы
class Btn(Button):
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards)
self.pack(expand=YES, fill=BOTH, side=LEFT)
f = Frame() # Фрейм
f.pack(expand=YES, fill=BOTH)
for j in range(column):
Btn(f, width=3, height=2, font=('times', 24, 'bold'))
mainloop() # главный цикл программы
Лист. 6. Кнопки во фрейме.
Рис. 4. Ряд кнопок создан программой лист. 6.
from tkinter import * # Графическая библиотека
column = 3 # Столбцы
row = 3 # Строки
class Btn(Button): # Класс Btn
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards)
self.pack(expand=YES, fill=BOTH, side=LEFT)
for i in range(row):
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки
Btn(f, width=3, height=2, font=('times', 24, 'bold'))
mainloop() # Главный цикл программы
Лист. 7. GUI приложение с решёткой кнопок.
Рис. 5. Приложение созданное программой листинг 7.
from tkinter import * # Графическая библиотека
column = 3 # Столбцы
row = 3 # Строки
class Btn(Button): # Класс Btn
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
def play(self): # Обработчик нажатия на кнопку
self.config(text='*')
for i in range(row):
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки
Btn(f, width=3, height=2, font=('times', 24, 'bold'))
mainloop() # Главный цикл программы
Лист. 8. В программу, в класс Btn добавлен метод play().
Рис. 6. Приложение созданное программой листинг 8.
Метод play(), экземпляров класса Btn, по щелчку мышью на кнопке выводит на эту кнопку звёздочку (*).
Крестики нолики
from tkinter import * # Графическая библиотека
column = 3 # Столбцы
row = 3 # Строки
class Btn(Button): # Класс Btn
who = True # Кто ходит
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
def play(self): # Обработчик нажатия на кнопку
if Btn.who:
self.config(text='X')
else:
self.config(text='0')
Btn.who = not(Btn.who)
for i in range(row):
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки
Btn(f, width=3, height=2, font=('times', 24, 'bold'))
mainloop() # Главный цикл программы
Лист. 9.
Рис. 7.
#!/usr/bin/env python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
#
# tic-tac-toe.py
# Copyright (C) 2025 Aleksandr Diorditsa, see <https://adior.ru>
# I want to thank all my students for the inspiration they give me.
#
# tic-tac-toe.py is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# tic-tac-toe.py is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
from tkinter import * # Графическая библиотека
column = 3 # Столбцы
row = 3 # Строки
class Btn(Button): # Класс Btn
who = True # Кто ходит
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
def play(self): # Обработчик нажатия на кнопку
if self.cget('text') != '': return
self.config(text='X' if Btn.who else '0')
Btn.who = not(Btn.who)
for i in range(row):
f = Frame() # Фреймы (строки)
f.pack(expand=YES, fill=BOTH)
for j in range(column): # Колонки
Btn(f, width=3, height=2, font=('times', 24, 'bold'))
mainloop() # Главный цикл программы
Лист. 10.
Рис. 8.
Что ест уж
арвар
from tkinter import * # графическая библиотека
column = 3 # столбцы
row = 3 # строки
class Btn(Button):
playground = list('ЧТОЕСТЖУ ') # виртуальное игровое поле
def __init__(self, num, *args, **kwards):
super().__init__(*args, **kwards, command=self.play,
text=self.playground[num])
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = num
def play(self): # обработчик нажатия на кнопку
self.config(text=' ')
for i in range(row):
f = Frame() # Фреймы
f.pack(expand=YES, fill=BOTH)
for j in range(column):
n = i * column + j
Btn(n, f, width=3, height=2, font=('times', 24, 'bold'))
mainloop() # главный цикл программы
Лист. 14.
Рис. 9.
from tkinter import * # графическая библиотека
column = 3 # столбцы
row = 3 # строки
class Btn(Button):
playground = list('ЧТОЕСТЖУ ') # виртуальное игровое поле
def __init__(self, num, *args, **kwards):
super().__init__(*args, **kwards, command=self.play,
text=self.playground[num])
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = num
def play(self): # обработчик нажатия на кнопку
n = self.num
m = self.playground.index(" ")
self.config(text=' ')
self.playground[m], self.playground[n] = self.playground[n], " "
for i in range(row):
f = Frame() # Фреймы
f.pack(expand=YES, fill=BOTH)
for j in range(column):
n = i * column + j
Btn(n, f, width=3, height=2, font=('times', 24, 'bold'))
mainloop() # главный цикл программы
Лист. 15.
Рис. 10.
from tkinter import * # графическая библиотека
column = 3 # столбцы
row = 3 # строки
class Btn(Button):
playground = list('ЧТОЕСТЖУ ') # виртуальное игровое поле
def __init__(self, num, *args, **kwards):
super().__init__(*args, **kwards, command=self.play,
text=self.playground[num])
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = num
self.automove()
def play(self): # обработчик нажатия на кнопку
n = self.num
m = self.playground.index(" ")
self.config(text=' ')
self.playground[m], self.playground[n] = self.playground[n], " "
self.automove()
def automove(self): # функция кнопки с пробелом
self.config(text=self.playground[self.num])
if self.cget('text') == " ":
self.after(300, self.automove)
for i in range(row):
f = Frame() # Фреймы
f.pack(expand=YES, fill=BOTH)
for j in range(column):
n = i * column + j
Btn(n, f, width=3, height=2, font=('times', 24, 'bold'))
mainloop() # главный цикл программы
Лист. 16. В программе, в функции Btn.automove() используется рекурсивный отложенный вызов с помощью функции after().
Рис. 11.
#!/usr/bin/env python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
#
# snake.py
# Copyright (C) 2021 Aleksandr Diorditsa, see <https://adior.ru>
# I want to thank all my students for the inspiration they give me.
#
# snake.py is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# snake.py is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
from tkinter import * # графическая библиотека
column = 3 # столбцы
row = 3 # строки
class Btn(Button):
playground = list('ЧТОЕСТЖУ ') # виртуальное игровое поле
def __init__(self, num, *args, **kwards):
super().__init__(*args, **kwards, command=self.play,
text=self.playground[num])
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = num
self.automove()
def play(self): # обработчик нажатия на кнопку
n = self.num
m = self.playground.index(" ")
if (n in [m+1, m-1] and m // column == n // column
or n in [m-column, m+column]):
self.config(text=' ')
self.playground[m], self.playground[n] = self.playground[n], " "
self.automove()
def automove(self): # функция кнопки с пробелом
self.config(text=self.playground[self.num])
if self.cget('text') == " ":
self.after(300, self.automove)
for i in range(row):
f = Frame() # Фреймы
f.pack(expand=YES, fill=BOTH)
for j in range(column):
n = i * column + j
Btn(n, f, width=3, height=2, font=('times', 24, 'bold'))
mainloop() # главный цикл программы
Лист. 17. В программе, в функции Btn.automove() используется рекурсивный отложенный вызов с помощью функции after(). В функцию play() добавлена функция if с правилами игры в условии.
Рис. 12.
#!/usr/bin/env python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
#
# snake.py
# Copyright (C) 2021 Aleksandr Diorditsa, see <https://adior.ru>
# I want to thank all my students for the inspiration they give me.
#
# snake.py is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# snake.py is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
from tkinter import * # графическая библиотека
column = 3 # столбцы
row = 3 # строки
playground = list('ЧТОЕСТЖУ ') # виртуальное игровое поле
class Btn(Button):
space = 8
def __init__(self, num, *args, **kwards):
super().__init__(*args, **kwards, command=self.play)
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = num
def play(self): # обработчик нажатия на кнопку
n = self.num
m = Btn.space
if (n in [m+1, m-1] and m // column == n // column
or n in [m-column, m+column]):
playground[m].set(playground[n].get())
playground[n].set(" ")
Btn.space = n
for i in range(row):
f = Frame() # Фреймы
f.pack(expand=YES, fill=BOTH)
for j in range(column):
n = i * column + j
playground[n] = StringVar(f, playground[n])
Btn(n, f, width=3, height=2, font=('times', 24, 'bold'),
textvariable=playground[n])
mainloop() # главный цикл программы
Лист. 18. Свойство textvariable объектов класса Button связано с переменной типа StringVar.
#!/usr/bin/env python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
#
# snake.py
# Copyright (C) 2021 Aleksandr Diorditsa, see <https://adior.ru>
# I want to thank all my students for the inspiration they give me.
#
# snake.py is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# snake.py is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
from tkinter import * # графическая библиотека
column = 3 # столбцы
row = 3 # строки
btn = [] # список кнопок
class Btn(Button):
playground = list('ЧТОЕСТЖУ ') # виртуальное игровое поле
def __init__(self, num, *args, **kwards):
super().__init__(*args, **kwards, command=self.play,
text=self.playground[num])
self.pack(expand=YES, fill=BOTH, side=LEFT)
self.num = num
def play(self): # обработчик нажатия на кнопку
n = self.num
m = self.playground.index(" ")
if (n in [m+1, m-1] and m // column == n // column
or n in [m-column, m+column]):
self.config(text=' ')
btn[m].config(text=self.playground[n])
self.playground[m], self.playground[n] = self.playground[n], " "
for i in range(row):
f = Frame() # Фреймы
f.pack(expand=YES, fill=BOTH)
for j in range(column):
n = i * column + j
btn += [Btn(n, f, width=3, height=2, font=('times', 24, 'bold'))]
mainloop() # главный цикл программы
Лист. 19. Программа содержит список объектов класса Button, то есть, объекты поименованы.
#!/usr/bin/env python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
#
# snake.py
# Copyright (C) 2021 Aleksandr Diorditsa, see <https://adior.ru>
# I want to thank all my students for the inspiration they give me.
#
# snake.py is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# snake.py is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
from tkinter import * # графическая библиотека
column = 3 # столбцы
row = 3 # строки
btn = [] # список кнопок
playground = list('ЧТОЕСТЖУ ') # виртуальное игровое поле
class Btn(Button):
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards)
self.pack(expand=YES, fill=BOTH, side=LEFT)
def play(n): # обработчик нажатия на кнопку
m = playground.index(" ")
if (n in [m+1, m-1] and m // column == n // column
or n in [m-column, m+column]):
playground[m], playground[n] = playground[n], " "
btn[n].config(text=" ")
btn[m].config(text=playground[m])
for i in range(row):
f = Frame() # Фреймы
f.pack(expand=YES, fill=BOTH)
for j in range(column):
n = i * column + j
btn += [Btn(f, width=3, height=2, font=('times', 24, 'bold'),
text=playground[n], command=lambda n=n: play(n))]
mainloop() # главный цикл программы
Лист. 20. Программа с lambda функцией.
#!/usr/bin/env python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
#
# snake.py
# Copyright (C) 2021 Aleksandr Diorditsa, see <https://adior.ru>
# I want to thank all my students for the inspiration they give me.
#
# snake.py is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# snake.py is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
from tkinter import * # графическая библиотека
column = 3 # столбцы
row = 3 # строки
btn = [] # список кнопок
playground = list('ЧТОЕСТЖУ ') # виртуальное игровое поле
class Btn(Button):
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards)
self.pack(expand=YES, fill=BOTH, side=LEFT)
class Letter:
def __set__(self, instance, value):
instance.config(text=value)
letter = Letter()
def play(n): # обработчик нажатия на кнопку
m = playground.index(" ")
if (n in [m+1, m-1] and m // column == n // column
or n in [m-column, m+column]):
btn[m].letter, btn[n].letter = playground[m], playground[n] = playground[n], " "
for i in range(row):
f = Frame() # Фреймы
f.pack(expand=YES, fill=BOTH)
for j in range(column):
n = i * column + j
btn += [Btn(f, width=3, height=2, font=('times', 24, 'bold'),
text=playground[n], command=lambda n=n: play(n))]
mainloop() # главный цикл программы
Лист. 21. Класс Btn с дескриптором Letter, который содержит функцию __set__ .
#!/usr/bin/env python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*-
#
# snake.py
# Copyright (C) 2021 Aleksandr Diorditsa, see <https://adior.ru>
# I want to thank all my students for the inspiration they give me.
#
# snake.py is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# snake.py is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
from tkinter import * # графическая библиотека
column = 3 # столбцы
row = 3 # строки
btn = [] # список кнопок
class Btn(Button):
def __init__(self, *args, **kwards):
super().__init__(*args, **kwards)
self.pack(expand=YES, fill=BOTH, side=LEFT)
class Letter:
def __set__(self, instance, value):
instance.config(text=value)
def __get__(self, instance, owner):
return instance.cget('text')
letter = Letter()
def play(n): # обработчик нажатия на кнопку
m = [i.letter for i in btn].index(" ")
if (n in [m+1, m-1] and m // column == n // column
or n in [m-column, m+column]):
btn[m].letter, btn[n].letter = btn[n].letter, " "
for i in range(row):
f = Frame() # Фреймы
f.pack(expand=YES, fill=BOTH)
for j in range(column):
n = i * column + j
btn += [Btn(f, width=3, height=2, font=('times', 24, 'bold'),
text='ЧТОЕСТЖУ '[n], command=lambda n=n: play(n))]
mainloop() # главный цикл программы
Лист. 22. Класс Btn с дескриптором Letter, который содержит функции __set__ и __get__.
Литература: proglib