2010-06-19 57 views
11

我一直在阅读描述类继承,抽象基类甚至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。给Shape添加这样的东西并不能解决问题:

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

我在做什么错了?整个想法是否被严格执行?任何帮助不胜感激。

+0

'__getattr__'仅适用于新样式类的作品。这意味着你的类必须是'object'的子类。 – 2010-06-19 18:07:29

+0

你正在做的事情也被称为具有虚拟构造函数的类(而不是“虚拟类”)。参见相关的问题[_什么是类工厂?](http://stackoverflow.com/questions/2526879/what-exactly-is-a-class-factory) – martineau 2016-12-02 03:03:22

回答

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) 

或:

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] 

和形状

class Line(Shape): 
    def __init__(self, description): 
     self.desc = description 
    def number_of_edges(self, parameters): 
     return 1 
继承的类
+0

您的第二个工厂函数构造每个类型的对象时间被称为,即使你只返回其中的一个。最好在字典中存储比对象更多的类:'class_dict = {“It flat”:Line,...}'then'return class_dict [description](description)'。 – 2017-09-21 10:45:55

0

您可以object.__class__更改类,但是做一个返回任意类的实例的函数会更好。

在另一方面,所有类应该从object继承,除非您使用使用Python 3,这样,否则你结束了一个旧样式类:

class A(object): 
    pass 
1

Python没有虚拟班列的盒子。你将不得不自己实现它们(应该有可能,Python的反射能力应该足够强大,可以让你这样做)。但是,如果你需要虚拟类,那么为什么你不使用一种编程语言,它具有像Beta,gBeta或Newspeak这样的虚拟类? (顺便说一下:还有其他的吗?)

但是,在这个特殊情况下,我并不真正看到虚拟类如何简化您的解决方案,至少在您给出的示例中不是这样。也许你可以阐述为什么你认为你需要虚拟课程?

不要误解我的意思:我喜欢虚拟课程,但实际上只有三种语言实现了它们,其中三种语言中只有一种仍然存在,而其中三种实际上只有其中的0种实际上被任何人使用, …

+1

*顺便说一句:有没有其他人?*:想到C++。 – user1717828 2016-02-20 20:03:31

+0

有趣!我不知道。你有链接,我可以阅读C++中的虚拟类吗?根据维基百科,在C++中,嵌套类是封闭类的静态成员。换句话说:它们实际上不是真*嵌套类(它是封闭类的封闭*实例*的成员)。考虑到虚拟类是真正的嵌套类的特例(即像其他虚拟成员一样在子类中重写的真正的嵌套类),这似乎排除了C++具有虚拟类。 – 2016-02-21 11:07:59

+0

Mmm,AFAIK C++类定义了什么是虚拟类,因为这种语言非常流行,并且对它们进行了大量的使用。 [虚拟/抽象类](https://en.m.wikipedia.org/wiki/Virtual_method_table#Example)不能被实例化,只能被继承,所以更像是其他类的模板。 – user1717828 2016-02-21 12:41:18

18

我同意TooAngel,但我会使用__new__ method

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. 
+1

不错 - 我也想过类似的东西,但不知道它的Python语法 – TooAngel 2010-06-19 18:28:43

+0

在这个例子中,Shape被称为_metaclass_。 – 2010-06-19 18:32:42

+2

@Daniel:我不这么认为。元类通常改变一个班级的工作方式。在Objective-C中,这将被称为*类集群*。我不确定它在Python中的名称是什么。 – 2010-06-19 19:22:09