Различия между версиями 9 и 10
Версия 9 от 2017-08-13 18:12:44
Размер: 9534
Редактор: FrBrGeorge
Комментарий:
Версия 10 от 2017-08-13 18:14:45
Размер: 9510
Редактор: FrBrGeorge
Комментарий:
Удаления помечены так. Добавления помечены так.
Строка 109: Строка 109:
  * ''содержащего '''docstring''', описывающий, что такое объект класса `Square`''
  * ''
содержащего `pygame.Rect`''
  * ''
с методом `show(self, surface)`, рисующим квадрат на `surface`''
  * ''
с методом `ID(self)`, выдающим строку с описанием объекта''
  * ''
содержащего информацию о цвете `(pygame.Color)`''
  * содержащего `docstring`, описывающий, что такое объект класса `Square`
  *
содержащего `pygame.Rect`
  *
с методом `show(self, surface)`, рисующим квадрат на `surface`
  *
с методом `ID(self)`, выдающим строку с описанием объекта
  *
содержащего информацию о цвете `(pygame.Color)`

Введение в ООП; классы; инкапсуляция

Не успели в 7 день

  • itertools

Построение графиков в PyGame

  • нарисуем ломаную
    • pygame.draw.lines()

    • например, график функции y = sqrt(x) или y = sin(x)

    • график 1:1px очень мелкий; особенно забавным получается sin(x)

      • нужно прибегать к масштабированию и смещению осей, т. е. экранных координат
  • Напишем функцию scale(x,a,b,A,B), которая по числу x на отрезке a…b вычисляет число X на отрезке A…B, делящее этот отрезок в той же пропорции

    • (подсказка) scale(a,a,b,A,B) == A, scale(b,a,b,A,B) == B, scale((a+b)/2,a,b,A,B) == (A+B)/2

      • (спойлер!) вычесть начало старого отрезка (получится что-то от 0), поделить на длину отрезка (получится что-то от 0 до 1), умножить на длину нового отрезка, прибавить его начало
  • {*} Нарисовать sin(x) на отрезке a≤x≤b, 100 точек в графике, график растянут на всё окно

    •    1 # Ввести A и B,
         2 # Нарисовать график функции sin(x),
         3 # где A≤x≤B, 100 точек в графике
         4 # график должен помещаться во всё окно
         5 
         6 import pygame
         7 from math import *
         8 
         9 W, H = 320,200
        10 N = 100
        11 
        12 pygame.init()
        13 
        14 screen = pygame.display.set_mode((W,H))
        15 A, B = -3, 4
        16 X = [A+(B-A)*i/(N-1) for i in range(N)]
        17 Dots = [(x,sin(x)) for x in X]
        18 Graph = [ ((x-A)*W/(B-A), (y+1)*H/2) for x,y in Dots]
        19 pygame.draw.lines(screen, (255,255,0,255), False, Graph)
        20 
        21 while pygame.event.wait().type != pygame.QUIT:
        22     pygame.display.flip()
      
  • {*} Переписать предыдущее задание с использованием масштабирующей функции scale

  • {*} Попробовать при помощи scale уместить график в прямоугольник заданных размеров

    •    1 # переписать программу рисования синуса
         2 # с использованием функции масштабирования
         3 # scale(x,a,b,A,B), которая x из диапазона a…b превращает
         4 # в X из диапазона A…B
         5 # уместить график в заданный прямогугольник
         6 
         7 import pygame
         8 from math import *
         9 
        10 def scale(x,a,b,A,B):
        11     return (x-a)*(B-A)/(b-a)+A
        12 
        13 W, H = 320,200
        14 N = 100
        15 Grect = pygame.Rect(10,5,W-20,H-10)
        16 pygame.init()
        17 
        18 screen = pygame.display.set_mode((W,H))
        19 A, B = -3, 4
        20 X = [scale(i,0,N-1,A,B) for i in range(N)]
        21 Dots = [(x,sin(x)) for x in X]
        22 Graph = [(scale(x,A,B,Grect.left,Grect.right), scale(y,-1,1,Grect.top,Grect.bottom)) for x,y in Dots]
        23 pygame.draw.lines(screen, (255,255,0,255), False, Graph)
        24 
        25 while pygame.event.wait().type != pygame.QUIT:
        26     pygame.display.flip()
      
  • К зачёту: Поправить пример:

    • добавить возможность таскать график мышью
    • добавить масштабирование колесом
    • нарисовать оси координат
      • <!> оси координат должны всегда быть видны

Классы

  • Можно почитать скетч про классы в Python3

  • класс по имени someclass — это тоже такой объект

    • callable(someclass) == True

    • (type(some) is type) == True"

    • ...такой объект с полями
      • aka static class members в других языках

  • класс можно инстанциировать — создать экземпляр класса, объект класса

    • a = someclass()

      • (type(a)) is someclass) == True

    • такой объект — не что иное, как пространство имён
      • TODO вспомним: а чем отличается от словаря?
    • к объекту можно добавлять поля, которых класс изначально не предусматривал
    • при обращении к callable-полям класса через объект мы получаем не само поле, а обёртку над ним, имеющую тип method:

      • def ff(...): ...

      • some.fn = ff

      • type(some.fn) is type(ff) == True

      • type(a.fn) is type(ff) == False

      • вызов метода a.fn(*args) аналогичен вызову функции-поля класса some.fn(a, *args)

  • Некоторые методы и поля (вида __blabla__) имеют особенное значение

    • __init__(), aka конструктор

    • __class__ — тип объекта; класс, экземпляром которого он является

    • __str__() — преобразование в строку

    • __eq__() — операция сравнения (==)

      • 'запись на Python' a == 2 'эквивалентна записи' a.__eq__(2)

    • __add__() — операция сложения

    • тысячи их!

    • естественно, их можно переопределять (перегружать)

      • тем самым наделять различные конструкции языка смыслом
      • например, def __eq__(self, ob): ...

    • левые/правые операции
      • если a.__add__(b) возвращает NotImplemented, то Python пытается подставить b.__radd__(a)

  • {*} создать cписок из 10 экземпляров класса Square:

    • содержащего docstring, описывающий, что такое объект класса Square

    • содержащего pygame.Rect

    • с методом show(self, surface), рисующим квадрат на surface

    • с методом ID(self), выдающим строку с описанием объекта

    • содержащего информацию о цвете (pygame.Color)

    • задать каждому координаты, размер, цвет
    • нарисовать, пользуясь методами класса
         1 # создать класс Square, который должен
         2 # - содержать размер и координатвы (pygame.Rect)
         3 # - содержать цвет (pygame.Color)
         4 # - содержать метод show(self, surface) — нарисовать себя на surface
         5 # - содержать метод ID(self) — строка с описанием объекта
         6 # создать список из 10 таких прямоугольников, задать их координаты, размер и цвет
         7 # нарисовать все
         8 
         9 import pygame
        10 import random
        11 
        12 def randcolor():
        13     col = [random.randrange(100,255),random.randrange(0,255),random.randrange(0,100)]
        14     random.shuffle(col)
        15     return pygame.Color(*col)
        16 
        17 class Square:
        18     rect = pygame.Rect(0,0,0,0)
        19     color = pygame.Color(0,0,0,0)
        20     
        21     def show(self, surface):
        22         pygame.draw.rect(surface, self.color, self.rect)
        23         
        24     def ID(self):
        25         return "Square: {}/{}".format(self.rect, self.color)
        26         
        27 W, H = 320, 200
        28 pygame.init()
        29 screen = pygame.display.set_mode((W, H))
        30 
        31 SQS = [Square() for i in range(10)]
        32 for s in SQS:
        33     s.color = randcolor()
        34     s.rect = pygame.Rect(random.randrange(0, W-10),  random.randrange(0, H-10), 10, 10)
        35     
        36 for s in SQS:
        37     s.show(screen)
        38     
        39 while pygame.event.wait().type != pygame.QUIT:
        40     pygame.display.flip()
      
  • {i} реализовать класс Rect как Square:

    • поддержка сложения, ( <!> вычитания, умножения на число)

      • /!\ pygame.Rect сами собой не складываются, надо выдумать для них сложение (например, результат — прямоугольник суммарного размера по координатам первого слагаемого)

      • /!\ pygame.Color при сложении довольно быстро дают белый, интереснее брать полусумму цветов (примерно так: self.color//pygame.Color(2,2,2,1)+other.color//pygame.Color(2,2,2,1))

      • при этом вместо двух старых образуется один новый, пока не останется один :)

    • отображение на экран
    • К зачёту: программа, которая умеет рисовать такие прямоугольники, таскать их по экрану и при переносе одного прямоугольника на другой складывает их

Python/Summer2017/2017-07-12 (последним исправлял пользователь FrBrGeorge 2017-08-13 18:14:45)