Соответствует ли мой код парадигме ООП?
Совсем нет.
Мне не хочется переделывать твой код построчно, он плох (это нормально, а то, что он работает - просто отлично). Надо бы как-то так:from abc import ABC, abstractmethod
from math import sin, cos, pi


class Figure(ABC):
    def __init__(self, height=2):
        assert 1 < height < 20  # незачем больше
        self.height = height

    @abstractmethod
    def draw(self):
        pass


class Triangle(Figure):
    def draw(self):
        for i in range(self.height - 1):
            print(f'{"/":>{self.height - i}}{"":>{i * 2}}\\')
        print('─' * (self.height * 2))


class Square(Figure):
    def draw(self):
        w = self.height * 2 - 2
        print('┌', '┐', sep='─' * w)
        for _ in range(self.height - 2):
            print('│', '│', sep=' ' * w)
        print('└', '┘', sep='─' * w)


class Ellipse(Figure):
    def __init__(self, height=7, width=None):
        assert 6 < height < 20  # меньше никак
        if width is None:
            width = height
        else:
            assert 6 < width < 20
        self.height, self.width = height, width

    def draw(self):
        buf = [[' '] * (self.width * 2) for _ in range(self.height)]
        rx, ry = self.width - 1., self.height / 2 - .5
        for i in range(100):
            φ = i * pi / 50
            buf[round(ry * (1 + sin(φ)))][round(rx * (1. + cos(φ)))] = '*'
        for row in buf:
            print(''.join(row))


Triangle(7).draw()
Square(7).draw()
Ellipse(7).draw()
Ellipse(17, 7).draw()
Смотри на иерархию классов, о реализации методов не запаривайся.
ООП как парадигма требует строгую наследственность, ее нет, то это не ООП, как бы вас это не смущало )