2012-04-22 43 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等等。