Форум сайта python.su
0
Добрый день. Есть желание попрактиковаться в ООП.
Начал решать задачку по расширению классов. Сразу возник вопрос как отличить класс от модуля?
При импорте библиотеки PIL : from PIL import Image, ImageDraw
ImageDrive - это класс или модуль?
При создании дочернего класса он должен унаследовать все атрибуты и методы родительского класса. Т.е если дочерний класс создать пустым то его экземпляры должны вести себя точно так же как экземпляры родительского класса.
Тогда почему не работает код в colabe ? выдает ошибку что в новом классе не существует атрибутов? Его родитель ведь определен?
Первая ячейка в колабе использует для рисования ImageDraw. Вторая - новый класс NewImageDrive.
Отредактировано dmitry_79 (Янв. 13, 2023 08:46:42)
Офлайн
124
from PIL import ImageDraw print(type(ImageDraw)) print(ImageDraw) print(ImageDraw.ImageDraw) print(ImageDraw.Image.Image)
Отредактировано xam1816 (Янв. 13, 2023 10:50:25)
Офлайн
0
Это первое что я сделал.
<class ‘module’>
<class ‘type’>
<class ‘PIL.Image.Image’>
Как интерпретировать этот вывод?
Это все классы?
Офлайн
124
без type выведи все
print(ImageDraw)
Офлайн
0
Убрал 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)
Офлайн
857
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Ты лучше сбрось код сюда. Как-то не хочется в Google заходить, чтобы это было возможно запускать или редактировать. Так-то он тебе говорит, что ты пытаешься в классе найти Draw, которая является функцией в модуле.
Первая ячейка в колабе использует для рисования ImageDraw. Вторая - новый класс NewImageDrive.
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)
Офлайн
124
dmitry_79там написано что есть модуль, что есть класс.
Убрал type. Получил такой вывод:
dmitry_79чтобы расширить класс, нужно понимать из чего он состоит, для этого нужно смотреть в документации из чего он состоит. Либо использовать
все равно ругается на отсутсвие метода Draw
help(ImageDraw)
Офлайн
0
Здорово! Спасибо за потраченное время на столь развернутый ответ!
Ваше видение ООП несколько отличается от того что имею я, со своим небольшим багажом.
Набросал следующий работающий код, который выводит красный треугольник в черном квадрате:
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 #создание дочернего класса 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)
Офлайн
857
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В нём нет метода рисования.
Вот код с созданием нового подкласса который должен наследовать все методы родительского класса. Метод рисования треугольника в нем пока точно такой же как и в предидущем коде, только вызыватся он должен из дочернего класса:
>>> 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() >>>
dmitry_79Я даже не знаю, кто тебя надоумил заняться этим “ООП”, которое не ООП. Ты же даже пространства имён не освоил, поэтому и не понимаешь, что никакого Draw там нет. Draw - это не метод класса, а это функция модуля. В модуле есть классы, а есть ещё функции, которые не принадлежат никаким классам. И вот эта Draw - одна из функций в модуле ImageDraw. А также в модуле ImageDraw есть класс с таким же именем ImageDraw. Если бы ты понимал пространства имён, что это такое и так далее, то для тебя бы эти сообщения об ошибках не представляли бы никакой загадки.
При выполении второго:
Отредактировано py.user.next (Янв. 13, 2023 13:43:41)
Офлайн
0
Вооот! Спасибо большое я увидел свою ошибку! И понял смысл Ваших слов насчет пространства имен. …надеюсь что понял. Надо уделить больше внимания этому вопросу!
Еще раз спасибо!
Офлайн