确定对象是面向对象分析和编程中最为重要的任务。
对象同时包含“数据”和“行为”。如果只对数据操作,使用列表、集合、字典或者python中的其他数据结构通常是更好的选择;如果只关注行为而不存储任何数据,那一个简单的函数则会更为合适。
把对象当做“对象”来对待,不能因为能够使用一个对象就急于使用这个对象,也绝不要在当你需要使用一个类的时候,疏于创建一个类。
下面列举了一个计算多边形周长的例子来说明面向对象和面向函数的区别。
面向函数编程如下:
import math def distance(p1, p2): return math.sqrt((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2) def perimeter(polygon): perimeter = 0 points = polygon + [polygon[0]] for i in range(len(polygon)): perimeter += distance(points[i], points[i+1]) return perimeter
具体调用如下所示:
>>> square = [(1,1), (1,2), (2,2), (2,1)] >>> print(perimeter(square)) 4.0
如果使用面向对象的编程,可以考虑封装点的列表(数据)和perimeter函数(行为)。
import math class Point: def __init__(self, x, y): self.x = x self.y = y def distance(self, p2): return math.sqrt((self.x - p2.x)**2 + (self.y - p2.y)**2) class Polygon: def __init__(self): self.vertices = [] def add_point(self, point): self.vertices.append((point)) def perimeter(self): perimeter = 0 points = self.vertices + [self.vertices[0]] for i in range(len(self.vertices)): perimeter += points[i].distance(points[i+1]) return perimeter
调用如下:
>>> square = Polygon() >>> square.add_point(Point(1,1)) >>> square.add_point(Point(1,2)) >>> square.add_point(Point(2,2)) >>> square.add_point(Point(2,1)) >>> square.perimeter() 4.0
相比而言,面向对象的代码要易读。
面向对象和面向函数的区别取决于怎样设计,一般来说,越是复杂的数据集,越容易需要对这些数据进行特定操作的函数,这时使用具有属性和方法的类也就越有价值。
另外需要额外注意的是,对象之间的交互,首先看继承关系,继承关系在没有类的情况下不可能被简单地模拟出来,所以一定要使用类来表现继承关系。另外还有关联和组合关系。
参考:
1、《Python3 面向对象编程》 [加]Dusty Philips 著