虚拟课程:做得对吗?

xAp*_*ple 11 python virtual inheritance class abstract

我一直在阅读描述类继承,抽象基类甚至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)
Run Code Online (Sandbox Code Playgroud)

我的重新路由远非最佳,因为只传递对number_of_edges()函数的调用.将这样的东西添加到Shape中并不能解决这个问题:

def __getattr__(self, *args):
    return underlying_class.__getattr__(*args)
Run Code Online (Sandbox Code Playgroud)

我做错了什么?整个想法是否得到了很好的实施?任何帮助非常感谢.

Geo*_*lly 18

我同意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
Run Code Online (Sandbox Code Playgroud)
>>> 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.
Run Code Online (Sandbox Code Playgroud)

  • @Daniel:我不这么认为.元类通常会改变类的工作方式.在Objective-C中,这将被称为*Class Cluster*.我不确定它的正确名称是什么. (3认同)

Too*_*gel 14

我更喜欢和工厂一起做:

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)
Run Code Online (Sandbox Code Playgroud)

要么:

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]
Run Code Online (Sandbox Code Playgroud)

并从Shape继承类

class Line(Shape):
    def __init__(self, description):
        self.desc = description
    def number_of_edges(self, parameters):
        return 1
Run Code Online (Sandbox Code Playgroud)

  • 你的第二个工厂函数在每次调用时构造一个每种类型的对象,即使你只返回其中一个.最好在字典中存储类而不是对象:`class_dict = {"它是扁平的":Line,...}`然后`return class_dict [description](description)`. (4认同)