170 похожих чатов

Вопрос по перегрузке методов отчасти: Есть три типа примитивов - точка(x,y),

прямоугольник(точка1, точка2) и отрезок(точка1, точка2)
Хочу чтобы можно было проверить, пересекаются ли объекты этих типов
* Точка пересекается с прямоугольником (лежит внутри)
* отрезок пересекается с отрезком
* отрезок пересекается с прямоугольником (лежит внутри хотя бы частично)
* прямоугольник пересекается с прямоугольником хотя бы частично
* ... возможно что-то еще
* если метод не реализован (например "точка лежит в отрезке") - бросать исключение.

Хочу чтобы проверки проходили как myLine.is_intersects_with(myBox)
При этом совсем не хочу в каждом классе делать is_intersects_with и писать условия для всех вариантов isinstanceof(other, Box).... elif isinstanceof(other, Segment) ... else

Хочу сделать так:
Все три класса - Point, Rect и Segment унаследовать от общего класса GeomPrimitive
В каждом классе прописать protected-методы для нахождения пересечения себя с другими типами примитивов соответственно именам классов

При этом дублировать код - прописывать в классе Box._is_intersects_with_segment и Segment._is_intersects_with_box я не хочу,
То есть хочу что если нет метода Box._is_intersects_with_segment то следует поискать метод Segment._is_intersects_with_box прозрачно для кода.
Соответственно прописать
class Segment:
def _is_intersects_with_box(self, other: Box)
def _is_intersects_with_segment(self, other: Point)
class Box:
def _is_intersects_with_point(self, other: Point)
def _is_intersects_with_box(self, other: Box)

И поиск нужного метода осуществлять в базовом классе GeomPrimitive через формирование названия метода как строки и поиска через getattr примерно так:
class GeomPrimitive:
def is_intersects_with(self, other_geom) -> bool:
method = getattr(self, f"_is_intersects_with_{str.lower(other_geom.__class__.__name__)}", None)
if callable(method):
return method(other_geom)
else:
method = getattr(other_geom, f"_is_intersects_with_{str.lower(self.__class__.__name__)}", None)
if callable(method):
return method(self)

raise NotImplementedError("Method instersection is not implemented between " +
f"{self.__class__.__name__} and {other_geom.__class__.__name__}.")

Вопрос - это адовый трешак так делать? Какие плюсы\минусы\камни в почках?
Как сделать более правильно, не увеличивая кодовую базу?

18 ответов

23 просмотра

Тебя на pastebin заблокировали?

Имхо не стоит в гетаттр запихивать ф строки, имхо дичь

Слишком много черточек, в глазах рябит

Слишком много магии

Tishka17
Слишком много магии

Ну там в целом какое то антиооп...

Почему нельзя сделать is_intersects и если вернул NotImplemented дергать у второго объекта?

Alexey D.-Filimonov Автор вопроса
Tishka17
Почему нельзя сделать is_intersects и если вернул ...

Чтобы в каждом классе не писать кучу IF-ов def is_instersects(self, other): if isinstance(other, Box): return self.__is_intersects_with_box(other) elif isinstance(other, Segment): return self.__is_intersects_with_box(other) raise NotImpl Хочется это как-то в более универсальное решение затолкать, наверное. И спасибо за хорошую идею с ловлей.

Alexey D. Filimonov
Чтобы в каждом классе не писать кучу IF-ов def is_...

Или вообще в отдельную функцию, которая будет пытаться вызывать нужные методы

Alexey D.-Filimonov Автор вопроса
Tishka17
А в базовый класс нельзя вынести?

Сравнение одного типа с другим - "везде своя логика".

Alexey D. Filimonov
Сравнение одного типа с другим - "везде своя логик...

Я пока не очень понимаю как это будет расширяться, но наверно в такой формулировке твой вариант допустим

Выглядит так, будто бы нужно использовать functools.singledispatch

Alexey D.-Filimonov Автор вопроса
Alexander
Выглядит так, будто бы нужно использовать functool...

Спасибо, кажется то, что нужно. Пошел изучать

Alexey D.-Filimonov Автор вопроса
Alexander
Выглядит так, будто бы нужно использовать functool...

Спасибо большое, всё что нужно получилось!

Похожие вопросы

Обсуждают сегодня

а через ESC-код ?
Alexey Kulakov
29
30500 за редактор? )
Владимир
47
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
13
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
6
program test; {$mode delphi} procedure proc(v: int32); overload; begin end; procedure proc(v: int64); overload; begin end; var x: uint64; begin proc(x); end. Уж не знаю...
notme
6
Ребят в СИ можно реализовать ООП?
Николай
33
у вас два процесса. один посылает другому сигнал. у вас есть код обоих процессов? если всё не так - расскажите как оно на самом деле. а именно кто кому чего, есть-ли консоли,...
Karagy
6
вы делали что-то подобное и как? может есть либы готовые? увидел картинку нокода, где всё линиями соединено и стало интересно попробовать то же в ddl на lua сделать. решил с ч...
Victor
8
Карта сайта