Виртуальные классы: делать правильно его?

Я читал документацию, описывающую наследование классов, абстрактные базовые классы и даже интерфейсы Python. Но ничто швы, чтобы быть точно, что я хочу. А именно, простой способ создать виртуальные классы. Когда виртуальный класс называют, я хотел бы, чтобы он инстанцировал некоторого более определенного класса на основе того, что параметры он дан, и вручите той спине функцию вызова. На данный момент у меня есть сводный способ перенаправить вызовы к виртуальному классу вниз к базовому классу.

Идея следующая:

class Shape:
    def __init__(self, description):
        if   description == "It's flat":  self.underlying_class = Line(description)
        elif description == "It's spiky": self.underlying_class = Triangle(description)
        elif description == "It's big":   self.underlying_class = Rectangle(description)
    def number_of_edges(self, parameters):
        return self.underlying_class(parameters)

class Line:
    def __init__(self, description):
        self.desc = description
    def number_of_edges(self, parameters):
        return 1

class Triangle:
    def __init__(self, description):
        self.desc = description
    def number_of_edges(self, parameters):
        return 3

class Rectangle:
    def __init__(self, description):
        self.desc = description
    def number_of_edges(self, parameters):
        return 4

shape_dont_know_what_it_is = Shape("It's big")
shape_dont_know_what_it_is.number_of_edges(parameters)

Мое перенаправление совсем не оптимально, как только вызовы к number_of_edges (), функция передается. Добавление чего-то вроде этого для Формирования не делает шва для добиваний цели также:

def __getattr__(self, *args):
    return underlying_class.__getattr__(*args)

Что я делаю неправильно? Вся эта мысль плохо реализована? Любая справка значительно ценится.

11
задан martineau 2 December 2016 в 03:03
поделиться

4 ответа

Я бы предпочел сделать это с помощью фабрики:

def factory(description):
    if   description == "It's flat":  return Line(description)
    elif description == "It's spiky": return Triangle(description)
    elif description == "It's big":   return Rectangle(description)

или:

def factory(description):
    classDict = {"It's flat":Line("It's flat"), "It's spiky":Triangle("It's spiky"), "It's big":Rectangle("It's big")}
    return classDict[description]

и наследовать классы от Shape

class Line(Shape):
    def __init__(self, description):
        self.desc = description
    def number_of_edges(self, parameters):
        return 1
14
ответ дан 3 December 2019 в 02:19
поделиться

В Python нет виртуальных классов "из коробки". Вам придется реализовать их самостоятельно (это должно быть возможно, возможности отражения Python должны быть достаточно мощными, чтобы вы могли это сделать).

Однако, если вам нужны виртуальные классы, почему бы вам просто не использовать язык программирования, у которого есть виртуальные классы, такие как Beta, gBeta или новояз? (Кстати: есть ли другие?)

Однако в данном конкретном случае я действительно не понимаю, как виртуальные классы упростили бы ваше решение, по крайней мере, не в приведенном вами примере. Может быть, вы могли бы уточнить, почему вы считаете, что вам нужны виртуальные классы?

Не поймите меня неправильно: мне нравятся виртуальные классы, но тот факт, что только три языка когда-либо реализовали их, только один из этих трех все еще жив и ровно 0 из этих трех на самом деле кто-нибудь в некоторой степени говорит…

1
ответ дан 3 December 2019 в 02:19
поделиться

Вы можете изменить класс с помощью объекта .__ class __ , но гораздо лучше просто создать функцию, которая возвращает экземпляр произвольного класса.

С другой стороны, весь класс должен наследовать от объекта , если вы не используете Python 3, как это, иначе вы получите класс старого стиля:

class A(object):
    pass
0
ответ дан 3 December 2019 в 02:19
поделиться

Я согласен с TooAngel, но я бы использовал __new__ метод.

class Shape(object):
    def __new__(cls, *args, **kwargs):
        if cls is Shape:                            # <-- required because Line's
            description, args = args[0], args[1:]   #     __new__ method is the
            if description == "It's flat":          #     same as Shape's
                new_cls = Line
            else:
                raise ValueError("Invalid description: {}.".format(description))
        else:
            new_cls = cls
        return super(Shape, cls).__new__(new_cls, *args, **kwargs)

    def number_of_edges(self):
        return "A shape can have many edges…"

class Line(Shape):
    def number_of_edges(self):
        return 1

class SomeShape(Shape):
    pass

>>> l1 = Shape("It's flat")
>>> l1.number_of_edges()
1
>>> l2 = Line()
>>> l2.number_of_edges()
1
>>> u = SomeShape()
>>> u.number_of_edges()
'A shape can have many edges…'
>>> s = Shape("Hexagon")
ValueError: Invalid description: Hexagon.
18
ответ дан 3 December 2019 в 02:19
поделиться
Другие вопросы по тегам:

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