【问题标题】:Why should I use classes in python?为什么我应该在 python 中使用类?
【发布时间】:2016-08-07 01:04:00
【问题描述】:

我是一个非常业余的 Python 学习者,最近开始学习类的概念。我可以(非常)大致理解类的概念,但我不明白为什么我不能简单地写一些函数而不是写一个类?

例如,(我正在向Interactive python 学习)给出的练习之一(我应该使用类来编写)是:

  1. 添加一个类似于distanceFromOrigindistanceFromPoint 方法,不同之处在于它将Point 作为参数并计算该点与自身之间的距离。

  2. Point 添加一个方法reflect_x,它返回一个新的Point,它是点关于x 轴的反射。例如,Point(3, 5).reflect_x()(3, -5)

他们使用这样的类编写代码:

import math

class Point:
    """ Point class for representing and manipulating x,y coordinates. """

def __init__(self, initX, initY):
    """ Create a new point at the given coordinates. """
    self.x = initX
    self.y = initY

def getX(self):
    return self.x

def getY(self):
    return self.y

def distanceFromOrigin(self):
    return ((self.x ** 2) + (self.y ** 2)) ** 0.5

def distanceFromPoint(self, otherP):
    dx = (otherP.getX() - self.x)
    dy = (otherP.getY() - self.y)
    return math.sqrt(dy**2 + dx**2)

p = Point(3, 3)
q = Point(6, 7)

print(p.distanceFromPoint(q))

既然我可以这么写,为什么还要使用类:

def distanceFromPoint(p,q): # they are tuples
    y = (p[0]-q[0])**(2)+(p[1]-q[1])**(2)
    return y**(1/2)

def reflectx(p):
    return (p[0],-p[1])

p = (3,3)
q = (6,7)

【问题讨论】:

  • 至少getXgetY 方法不被视为pythonic 代码。您可以直接访问xy 属性。
  • 除了以下更一般的答案:您实际上并不需要 getX/getY。 Python 没有真正的私有成员,所以只使用 x/y 是可以的。如果您需要覆盖它们,属性始终可用。
  • @Matthias:我是 python 新手。我不明白什么是 Python 代码,为什么 getX、getY 不是 Python 代码?
  • 你不需要为什么是或不是'Pythonic'而失眠,但我希望你看到mypoint.xmypoint.getX() 更简单、更清晰。但是,很难用这样一个简单的例子来说明 OOP 的力量。直到我有一个真正的问题要解决,我才真正“明白”,我突然意识到,如果我编写一个继承自其他人先前定义的类的类,这将是非常简单的。
  • @nekomatic:能否请您提一下 Python OOP 中的其中一个练习,它使您进入“啊哈”时刻?

标签: python class oop


【解决方案1】:

你可以在类之外声明一个函数。 但是将它们存储在类中通常在编程中是一种更好的做法。 OOP 被认为更具可读性和可重用性。

而且在这种情况下,两个之间的距离取决于点,所以在这个类中有 distanceFromPoint 方法是合乎逻辑的。

类还允许您确定计算距离 Points 的距离,而不是计算可能包含错误值的元组,例如两个以上的坐标。

【讨论】:

  • 我可以在我的距离函数中定义一个检查(使用 if 函数),如果前两个数据(在元组中)是整数,则计算,否则显示错误。那我为什么要使用类呢?
【解决方案2】:

Functionalobject-oriented 编程是不同的范例。

在 Python 中,一切都是对象,即使是 ints。整个语言都朝着面向对象的编程方向发展,这就是为什么你应该更喜欢它的原因,特别是如果你的程序会增长。

【讨论】:

  • 您混淆了函数式编程命令式编程。函数式编程并不意味着你使用函数。你可以在 Python 中进行函数式编程,但他在帖子中描述的方式是命令式编程
【解决方案3】:

使用 OOP 的一大优势是可扩展性

假设您编写了一个以点的形式处理大量数据的应用程序。现在您的客户添加到规范中,除了每个点的 x 和 y 坐标外,您的应用还需要知道每个点是什么颜色。

如果您编写的代码将每个点存储为元组(x, y),则可以将颜色添加为第三个值:(x, y, colour)。但是现在你必须检查你所有的代码来找到它被破坏的地方,因为你改变了数据格式。如果您使用了一个类,您可以简单地定义一个继承自 Point 并添加必要功能的新类:

class ColouredPoint(Point):
    """ Class for points which are coloured, based on Point """

    def __init__(self, initX, initY, initCol):
        Point.__init__(self, initX, initY)
        self.colour = initCol

p = ColouredPoint(3, 3, "green")
q = ColouredPoint(6, 7, "red")
r = Point(8, 4)

print(p.distanceFromPoint(q))
print(p.colour)
print(p.distanceFromPoint(r))

Point 类一起使用的所有代码仍将与新类一起使用,即使您没有编写或无法更改Point 类的定义,您也可以这样做。

【讨论】:

  • 代码损坏是什么意思?无类函数不能忽略附加值吗?例如,在没有类的情况下编码时,我可能在 p[2] 上有一个字符串作为元组,而元组在计算距离时会忽略它。
  • 没错,但是问题中的reflectx 函数呢?它会丢失额外的数据。我敢肯定,您可以想出一个解决方案,但我希望您看到,您想到的对原始文件的更改和扩展越多,设计始终正确运行的数据类型就越难。当您了解实际应用程序的复杂性时,OOP 更容易且更健壮,以上只是使用 OOP 的原因之一。
  • 如果我将类的需求总结为“添加新功能(以操作某些对象)或有效地更改对象的结构”,我是否遗漏了什么?使用 OOP 的其他原因是什么?
  • 除了可扩展性之外,OOP 还有很多特性,例如 1. 组织:- 在代码中描述和定义数据和过程。 2. 状态: - OOP 帮助您定义和跟踪状态。 3. 封装:过程和数据存储在一起。 4.继承:继承允许您在一个地方(在一个类中)定义数据和过程,然后稍后覆盖或扩展该功能。 5. 可重用性:所有这些原因和其他原因都允许代码具有更高的可重用性。面向对象的代码允许您编写可靠的(经过测试的)代码一次,然后一遍又一遍地重用。
【解决方案4】:

您的观点示例无法证明使用类的合理性。

类是描述事物是什么而不是操纵数据的好方法。所以一个点只有两位描述它的信息(无论如何在二维空间中)。

想一些更抽象的东西,比如电影文件。电影有各种与之相关的信息:标题、时长、类型、演员、年龄等级、受欢迎程度、语言、奖项……还在继续。尝试编写处理所有这些信息的长列表的函数,您将很快看到一个类的优点。

数学可能是一个真正没有那么多上下文信息的领域,只有几个变量,它们定义了一切。真实世界的数据定义不太明确,因此可以从类的可扩展性中受益。

【讨论】:

  • 您能否详细说明您的第二段(A 类很棒……)?没有太多示例,我无法清楚地理解这一点,而且我是 python 新手。
猜你喜欢
  • 2016-01-09
  • 2017-09-12
  • 2018-02-03
  • 2018-07-13
  • 1970-01-01
  • 2013-06-02
  • 2010-11-18
  • 2014-03-15
  • 2018-06-26
相关资源
最近更新 更多