Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 13, 2023 08:46:02

dmitry_79
Зарегистрирован: 2023-01-13
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Расширение класса ImageDraw

Добрый день. Есть желание попрактиковаться в ООП.
Начал решать задачку по расширению классов. Сразу возник вопрос как отличить класс от модуля?

При импорте библиотеки PIL : from PIL import Image, ImageDraw
ImageDrive - это класс или модуль?

При создании дочернего класса он должен унаследовать все атрибуты и методы родительского класса. Т.е если дочерний класс создать пустым то его экземпляры должны вести себя точно так же как экземпляры родительского класса.

Тогда почему не работает код в colabe ? выдает ошибку что в новом классе не существует атрибутов? Его родитель ведь определен?

Первая ячейка в колабе использует для рисования ImageDraw. Вторая - новый класс NewImageDrive.

Отредактировано dmitry_79 (Янв. 13, 2023 08:46:42)

Офлайн

#2 Янв. 13, 2023 10:48:43

xam1816
Зарегистрирован: 2020-05-11
Сообщения: 1394
Репутация: +  124  -
Профиль   Отправить e-mail  

Расширение класса ImageDraw

  
from PIL import ImageDraw
print(type(ImageDraw))
print(ImageDraw)
print(ImageDraw.ImageDraw)
print(ImageDraw.Image.Image)

Отредактировано xam1816 (Янв. 13, 2023 10:50:25)

Офлайн

#3 Янв. 13, 2023 10:53:26

dmitry_79
Зарегистрирован: 2023-01-13
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Расширение класса ImageDraw

Это первое что я сделал.

<class ‘module’>
<class ‘type’>
<class ‘PIL.Image.Image’>

Как интерпретировать этот вывод?
Это все классы?

Офлайн

#4 Янв. 13, 2023 10:56:39

xam1816
Зарегистрирован: 2020-05-11
Сообщения: 1394
Репутация: +  124  -
Профиль   Отправить e-mail  

Расширение класса ImageDraw

без type выведи все

  
print(ImageDraw)

Офлайн

#5 Янв. 13, 2023 11:05:40

dmitry_79
Зарегистрирован: 2023-01-13
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Расширение класса ImageDraw

Убрал type. Получил такой вывод:

<module ‘PIL.ImageDraw’ from ‘/usr/local/lib/python3.8/dist-packages/PIL/ImageDraw.py’>
<class ‘PIL.ImageDraw.ImageDraw’>
<class ‘PIL.Image.Image’>

Если я указываю эти имена в качестве родителя - все равно ругается на отсутсвие метода Draw

Отредактировано dmitry_79 (Янв. 13, 2023 11:07:02)

Офлайн

#6 Янв. 13, 2023 11:11:25

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10022
Репутация: +  857  -
Профиль   Отправить e-mail  

Расширение класса ImageDraw

dmitry_79
При импорте библиотеки PIL : from PIL import Image, ImageDraw
ImageDrive - это класс или модуль?
  
>>> import PIL
>>> 
>>> import PIL.ImageDraw
>>> 
>>> PIL.ImageDraw
<module 'PIL.ImageDraw' from '/usr/lib64/python3.6/site-packages/PIL/ImageDraw.py'>
>>> 
>>> PIL.ImageDraw.ImageDraw
<class 'PIL.ImageDraw.ImageDraw'>
>>>
>>> PIL.ImageDraw.Draw
<function Draw at 0x7f67f7389f28>
>>>

dmitry_79
Есть желание попрактиковаться в ООП.
ООП - это не то, что ты думаешь. Сначала отыскиваются абстракции, затем абстракции преобразуются в объекты, затем объекты группируются в классы, затем классы выстраиваются в единую иерархию классов, затем единая иерархия классов разбивается на уровни абстракции. Если получилось всё это сделать, значит правильная иерархия найдена; если не получилось всё это сделать, значит надо по новой всё проделать, чтобы получить в конечном итоге правильную иерархию. Если же ты думаешь, что ООП - это просто записать класс и пронаследоваться от него, то такое “ООП” тебе просто ничего не даст ни на малых программах, ни на больших.

dmitry_79
Т.е если дочерний класс создать пустым
Нет такого понятия “дочерний класс”, есть понятие подкласс. Подкласс/субкласс и надкласс/суперкласс. Есть также базовый класс, который находится на самом верху иерархии классов и не имеет суперкласса. Есть также неправильное толкование терминов, которое породил Страуструп. Из-за этого есть путаница в понятиях, потому что многие из них одноимённые, а по смыслу разные.

dmitry_79
Т.е если дочерний класс создать пустым то его экземпляры должны вести себя точно так же как экземпляры родительского класса.
Классы должны только расширять классы. Таким образом, все экземпляры подклассов по своей структуре и своему поведению являются экземплярами классов, от которых наследуются эти подклассы. Экземпляры подклассов могут только иметь дополнительные структурные элементы и дополнительное поведение.

dmitry_79
Первая ячейка в колабе использует для рисования ImageDraw. Вторая - новый класс NewImageDrive.
Ты лучше сбрось код сюда. Как-то не хочется в Google заходить, чтобы это было возможно запускать или редактировать. Так-то он тебе говорит, что ты пытаешься в классе найти Draw, которая является функцией в модуле.

help(PIL.ImageDraw)
FUNCTIONS
Draw(im, mode=None)
A simple 2D drawing interface for PIL images.

:param im: The image to draw in.
:param mode: Optional mode to use for color values. For RGB
images, this argument can be RGB or RGBA (to blend the
drawing into the image). For all other modes, this argument
must be the same as the image mode. If omitted, the mode
defaults to the mode of the image.



Отредактировано py.user.next (Янв. 13, 2023 11:12:59)

Офлайн

#7 Янв. 13, 2023 11:13:53

xam1816
Зарегистрирован: 2020-05-11
Сообщения: 1394
Репутация: +  124  -
Профиль   Отправить e-mail  

Расширение класса ImageDraw

dmitry_79
Убрал type. Получил такой вывод:
там написано что есть модуль, что есть класс.
dmitry_79
все равно ругается на отсутсвие метода Draw
чтобы расширить класс, нужно понимать из чего он состоит, для этого нужно смотреть в документации из чего он состоит. Либо использовать
  
help(ImageDraw)
если там что-то отсутствует, значит оно отсутствует и нет смысла вызывать это что-то отсутствующее

Офлайн

#8 Янв. 13, 2023 13:00:29

dmitry_79
Зарегистрирован: 2023-01-13
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Расширение класса ImageDraw

Здорово! Спасибо за потраченное время на столь развернутый ответ!
Ваше видение ООП несколько отличается от того что имею я, со своим небольшим багажом.

Набросал следующий работающий код, который выводит красный треугольник в черном квадрате:

 from PIL import Image, ImageDraw
# Create empty black canvas
im = Image.new('RGB', (255, 255))
dr = ImageDraw.Draw(im)
dr.polygon([(30,30), (30, 230), (220,130)], fill = (255,0,0))
display(im)

display(im) - особенность вывода в Google Colab. (не понимаю почему Вы его боитесь… Он охренительно облегчает жизнь в изучении пайтона… но не буду спорить, не в этом суть вопроса)

Теперь хочу расширить класс ImageDraw создав его подкласс NewImageDraw который, будет рисовать такой же равносторониий треугольник но новым методом, которому нужно передать координаты левой вершины и длинну стороны.

Вот код с созданием нового подкласса который должен наследовать все методы родительского класса. Метод рисования треугольника в нем пока точно такой же как и в предидущем коде, только вызыватся он должен из дочернего класса:
 from PIL import Image, ImageDraw
#создание дочернего класса
class NewImageDraw(ImageDraw.ImageDraw):
  pass
# Create empty black canvas
im = Image.new('RGB', (255, 255))
dr = NewImageDraw.Draw(im)
dr.polygon([(30,30), (30, 230), (220,130)], fill = (255,0,0))
display(im)

При выполнении первого кода ошибок нет.
При выполении второго:


Отредактировано dmitry_79 (Янв. 13, 2023 13:01:09)

Офлайн

#9 Янв. 13, 2023 13:32:11

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10022
Репутация: +  857  -
Профиль   Отправить e-mail  

Расширение класса ImageDraw

dmitry_79
Набросал следующий работающий код, который выводит красный треугольник в черном квадрате:
  
from PIL import Image, ImageDraw
# Create empty black canvas
im = Image.new('RGB', (255, 255))
dr = ImageDraw.Draw(im)
dr.polygon([(30,30), (30, 230), (220,130)], fill = (255,0,0))
display(im)
Вот этот код тоже выводит красный треугольник в чёрном квадрате
  
>>> from PIL import Image, ImageDraw
>>> 
>>> # Create empty black canvas
... im = Image.new('RGB', (255, 255))
>>> dr = ImageDraw.Draw(im)
>>> dr.polygon([(30,30), (30, 230), (220,130)], fill = (255,0,0))
>>> im.show()
>>>
Только для этого нужно просто в консоли питона запустить код.

dmitry_79
Вот код с созданием нового подкласса который должен наследовать все методы родительского класса. Метод рисования треугольника в нем пока точно такой же как и в предидущем коде, только вызыватся он должен из дочернего класса:
В нём нет метода рисования.

Вот этот рисуется через класс NewImageDraw
  
>>> from PIL import Image, ImageDraw
>>> 
>>> class NewImageDraw(ImageDraw.ImageDraw):
...   pass
... 
>>> im = Image.new('RGB', (255, 255))
>>> ndr = NewImageDraw(im)
>>> ndr.polygon([(30, 30), (30, 230), (220, 130)], fill = (255, 0, 0))
>>> im.show()
>>>
Как только ты метод .polygon() вызвал, тот сразу нарисовал это на картинке im.

dmitry_79
При выполении второго:
Я даже не знаю, кто тебя надоумил заняться этим “ООП”, которое не ООП. Ты же даже пространства имён не освоил, поэтому и не понимаешь, что никакого Draw там нет. Draw - это не метод класса, а это функция модуля. В модуле есть классы, а есть ещё функции, которые не принадлежат никаким классам. И вот эта Draw - одна из функций в модуле ImageDraw. А также в модуле ImageDraw есть класс с таким же именем ImageDraw. Если бы ты понимал пространства имён, что это такое и так далее, то для тебя бы эти сообщения об ошибках не представляли бы никакой загадки.



Отредактировано py.user.next (Янв. 13, 2023 13:43:41)

Офлайн

#10 Янв. 13, 2023 15:11:18

dmitry_79
Зарегистрирован: 2023-01-13
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Расширение класса ImageDraw

Вооот! Спасибо большое я увидел свою ошибку! И понял смысл Ваших слов насчет пространства имен. …надеюсь что понял. Надо уделить больше внимания этому вопросу!
Еще раз спасибо!

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version