2010-06-19 91 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