2012-04-22 25 views
3
import math 
class Point: 

    def __init__(self,x,y): 
     self.x = x 
     self.y = y 

    def move(self,x,y): 
     self.x += x 
     self.y += y 

    def __str__(self): 
     return "<"+ str(self.x) + "," + str(self.y) + ">" 


class Shape:   
    def __init__(self, centrePoint, colour, width, height): 
     self.centrePoint = centrePoint 
     self.colour = colour 
     self.width = width 
     self.height = height 
     self.type = "Square" 

    def __init__(self, centrePoint, radius, colour): 
     self.type = "Circle" 
     self.radius = radius 
     self.colour = colour 
     self.centrePoint = centrePoint 

    def move(self,x,y): 
     self.centrePoint.move(x,y) 

    def getArea(self): 
     if (self.type == "Square"): 
      return self.width * self.height 
     elif (self.type == "Circle"): 
      return math.pi*(self.radius**2) 

    def __str__(self): 
     return "Center Point: " + str(self.centrePoint) + "\nColour: "+ self.Colour + "\nType: " + self.type + "\nArea: " + self.getArea() 


class Rectangle (Shape): 

    def scale(self, factor): 
     self.scaleVertically(factor) 
     self.scaleHorizontally(factor) 

    def scaleVertically(self, factor): 
     self.height *= factor 

    def scaleHorizontally(self, factor): 
     self.width *= factor 

class Circle (Shape): 

    def scale(self, factor): 
     self.radius * factor 

這是我到目前爲止,形狀應該代表一個抽象類,其他兩個類都應該從它繼承的代碼,對我來說它仍然看起來太硬編碼爲一個抽象的解決方案,我怎麼能改進?Python的抽象編程

+2

這是http://codereview.stackexchange.com/的近乎完美的問題。 (ETA:請參閱[代碼評論常見問題](http://codereview.stackexchange.com/faq)瞭解它與StackOverflow的不同之處 - 通常詢問如何改進您的* working *代碼屬於前者) – 2012-04-22 16:42:05

+0

可以嗎暫時留在這裏?我可能需要問一些功能性問題。 – JamieB 2012-04-22 16:45:10

+0

有關此特定代碼的功能性問題會更好地問*和*更有可能在代碼評審中回答。如果除了「我怎樣才能讓這段代碼變得更好」之外,還有*新的*問題,那麼他們應該在StackOverflow上單獨提出問題。(同樣,你的問題沒有錯,我只是建議一個網站,你可以得到更有幫助的解決方案) – 2012-04-22 16:46:58

回答

4

我將在抽象類改變這一部分:

def getArea(self): 
    if (self.type == "Square"): 
     return self.width * self.height 
    elif (self.type == "Circle"): 
     return math.pi*(self.radius**2) 

您可以指定在抽象類中的默認和RectangleCircle覆蓋的方法。

但是,您可能會在https://codereview.stackexchange.com/上得到更好的答案。

UPDATE(實施例):

from abc import ABCMeta, abstractmethod 

class Shape: 
    __metaclass__ = ABCMeta 

    @abstractmethod 
    def getArea(self): 
    pass 

class Rectangle (Shape): 
    def getArea(self): 
    return self.width * self.height 

class Circle (Shape): 
    def getArea(self): 
    return math.pi*(self.radius**2) 

UPDATE 2(重載函數)

喜歡寫道,超載不蟒在這裏工作是避免過載的一個例子init funcktion:

def Shape: 
    def __init__(self, centrePoint, colour, **kwargs): 
    self.centrePoint = centrePoint 
    self.colour  = colour 
    self.width  = kwargs.get('width') 
    self.height  = kwargs.get('height') 
    self.radius  = kwargs.get('radius') 

個與

rect = Rectangle(0, "red", width=100, height=20) 
circ = Circle(0, "blue", radius=5) 

現在你可以創建對象約kwargs好的帖子是在這裏:What is a clean, pythonic way to have multiple constructors in Python?

類型變量也是無用的,因爲你可以用它來識別類型:

>>> rect = Rectangle(...) 
>>> print isinstance(rect, Rectangle) 
True 
>>> print isinstance(rect, Circle) 
False 
+1

+1但你也可以舉一個例子來代替它。 – jamylak 2012-04-22 17:05:10

+0

更新了一個例子。 – tbraun89 2012-04-22 17:16:17

2

首先,請注意python中沒有函數重載,因此:

class Shape:   
    def __init__(self, centrePoint, colour, width, height): 
     ... 

    def __init__(self, centrePoint, radius, colour): 
     ... 

將在第二個函數中「覆蓋」你的第一個函數。

根據經驗,一般情況下,一個共同的基/抽象類的概念背後的主要思想是解耦從接口的實現(注意蟒蛇約定,lower_case_with_underscores的函數名,不是camleCase):

class Shape: 
    __metaclass__ = ABCMeta 

    @abstractmethod 
    def get_area(self): 
    pass 

    move, scale, scale_vertically, scale_horizontally, print... 

現在,我已經我的抽象但可操作(如在「每個形狀可以被縮放,移動..」)基類,這是完全不知道的圓是如何構造的,移動或縮放。然後我可以開始執行子類:RectangleCircle等等。