На примере программы пинг-понг по стенкам демонстрируем работу функции after() из библиотеки Pyton tkinter. Функция after() (точнее, метод визуальных объектов) осуществляет задержку выполнения программы или отложенный вызов функции.

Первый параметр функции after() - время задержки в миллисекундах, а второй не обязательный параметр - имя вызываемой после задержки функции.

from tkinter import *                                   # Импорт функций из tkinter
fps = 9                                                 # Время обновления в мСек
rBall=25                                                # Радиус шарика
xSize = 800; ySize = 400                                # Размер canvas - rBall
xv = 1.4; yv = 2.7                                      # Скорость по х и у

def moveBall():                                         # Функция перемещения
    global xv, yv                                       # Скорости глобальные
    xyCoords = cnv.coords(1)                            # Текущая координата [x, y]
    if xyCoords[0] < rBall or xyCoords[0] > xSize:      # Предел по x
        xv *= -1                                        # Инверсия скорости по x
    if xyCoords[1] < rBall or xyCoords[1] > ySize:      # Предел по y
        yv *= -1                                        # Инверсия скорости по x
    cnv.move(1, xv, yv)                                 # Перемещение на шаг
    cnv.after(fps, moveBall)                            # Рекурсивный вызов с задержкой

cnv = Canvas(width=xSize+rBall, height=ySize+rBall)     # Создание холста
cnv.pack()                                              # Вывод холста на экран
img = PhotoImage(file='silver.png')                      # Создание объекта PhotoImage
cnv.create_image(50, 30, image=img, anchor=CENTER)      # Размещение PhotoImage на холсте
moveBall()                                              # Запуск движения
mainloop()                                              # Главный цикл программы

Программа 1. Пинг-понг по стенкам.

Рис. 1. Пинг-понг по стенкам.

ООП

Программа 1. короткая и не сложная, но попробуйте с помощью функций создать запустить в полёт с различными параметрами десятки шариков. Задача сильно усложнится.

Создавать шарики на экране и управлять их полётом будет удобнее как абстрактными объектами.

Абстрагирование означает выделение значимой информации и исключение из рассмотрения незначимой. В объектно-ориентированном программировании рассматривают лишь абстракцию данных, нередко называя её просто абстракцией и подразумевая набор наиболее значимых характеристик объекта, доступных остальной программе. 

Объектно-ориентированное программирование (ООП) — методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определённого класса, а классы образуют иерархию наследования.

Так же, как и абстракция, с ООП неразрывно связано понятие инкапсуляция. Инкапсуляция — свойство системы, позволяющее объединить данные и методы, работающие с ними, в классе. 

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

Переменная-объект, относящаяся к заданному классом типу, называется экземпляром класса. 

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

class car():
    def __init__(self, color=2):
        self.palette=['red','green','black','blue']
        self.color = color
    def set(self, color):
        self.color = color
    def get(self):
        return self.palette[self.color]
auto = car()
print(auto.get())
auto.set(1)
print(auto.get())

Программа 2.

Рис. 2. Изображения шариков в png формате.

#!/usr/bin/env python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- 
#
# brownian-motion.py
# Copyright (C) 2021 Aleksandr Diorditsa, see <https://adior.ru>
# I want to thank all my students for the inspiration they give me.
#
# brownian-motion.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.
# 
# brownian-motion.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 *
from random import *

file = ['red.png', 'yellow.png', 'gold.png', 'green.png',
        'emerald.png', 'cyan.png', 'blue.png', 'pink.png',
        'azure.png', 'bronze.png', 'purple.png',
        'scarlet.png', 'steel.png', 'silver.png']
rBall=25                                                # Радиус шарика
xSize = 800; ySize = 400                                # Размер canvas-rBall

class cnvBall:
    global rball, xSize, ySize
    def moveBall(self):
        xyCoords = self.cnv.coords(self.obj)
        if xyCoords[0] < rBall or xyCoords[0] > xSize:
            self.xv *= -1
        if xyCoords[1] < rBall or xyCoords[1] > ySize:
            self.yv *= -1
        self.cnv.move(self.obj, self.xv, self.yv)
        self.cnv.after(self.tic, self.moveBall)
    def __init__(self, cnv, img, x, y):
        self.cnv = cnv
        self.obj = cnv.create_image(x, y, image=img, anchor=CENTER)
        self.xv = 1; self.yv = 1
        self.tic = 10
        self.moveBall()

cnv = Canvas(width=xSize+rBall, height=ySize+rBall)
cnv.pack()
img = []; ball = []
for i in file: img.append(PhotoImage(file=i))
for j in range(30):
    for i in img: ball.append(cnvBall(cnv, i, choice(range(rBall, xSize)), choice(range(rBall, ySize))))
for i in range(420):
    ball[i].xv = random()*7-3.5
    ball[i].yv = random()*11-5.5
    ball[i].tic = choice(range(15, 30))

mainloop()

Программа 2. Броуновское движение.

В программе 2 мы создали класс cnvBall. Конструктор этого класса создаёт объект PhotoImage на холсте (Canvas), используя в качестве параметров объект класса Canvas, объект класса PhotoImage и координаты размещения PhotoImage на Canvas. Конструктор класса cnvBall,  так же, создаёт свойства объекта класса cnvBall: xv, yv и tic. Создав объект и свойства, конструктор запускает метод moveBall(). MoveBall(),  используя свойства xv и yv, как приращения координат, перемещает объект self.obj на холсте. Кроме того, в методе moveBall() вычисляются моменты столкновения перемещаемого объекта с границами холста и меняется знак соответствующих приращений координат xv или yv для изменения направления движения объекта.

В последней строке метода mooveBall() происходит рекурсивный вызов функции moveBall() с задержкой, созданной методом after(). Время задержки определяет свойство self.tic, передаваемое в функцию after() в качестве параметра. 

Рис. 3. Броуновское движение.