python为什么要用类_关于类:我为什么要在python中使用类?

本文探讨了Python中使用类而非简单函数的理由,通过举例展示了类在实现distanceFromPoint和reflect_x方法时的优势。类提供了可扩展性、封装和组织代码的能力,使得在数据结构发生变化或需要添加新功能时,代码更易于维护和理解。当应用涉及到多个相关属性和操作时,类的使用尤为关键。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

例如,(我从交互式Python学习)给出的练习之一(我应该用一个类来写)是:

添加一个与distanceFromOrigin类似的distanceFromPoint方法,只不过它以Point作为参数并计算该点与自身之间的距离。

将方法reflect_x添加到Point中,该方法返回新的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)

至少getX和getY方法不被视为pythonic代码。您可以直接访问x和y属性。

除了下面更一般的答案:你不需要GETX/GETY。python没有真正的私有成员,所以只使用x/y是可以的。如果需要覆盖它们,则属性始终可用。

@马提亚斯:我是Python的新手。我不明白什么是Python密码,为什么getx,gety不是Python密码?

你不需要因为什么是"Python"或什么不是"Python"而失眠,但我希望你看到,mypoint.x比mypoint.getX()更简单、更清晰。但在这样一个简单的例子中很难说明OOP的威力。直到我有真正的问题要解决,我才真正"明白",我突然意识到,如果我写了一个继承自其他人先前定义的类的类,那么这个类会非常简单。

@内科马蒂:你能提到那些在python oop中引导你进入"啊哈"时刻的练习吗?

正如我所说,这是一个真正的问题,而不是像你这样的练习,我以前没有见过基于我遇到的人工例子的OOP点。也许你能想到一些你真正想要创造的东西,并用这个过程作为学习这些技术的工具?

虽然您的问题似乎是"为什么选择OO",但我确实觉得至少在Python中过度使用了OO方法。我见过很多代码做简单的事情,使用OO没有(至少是显而易见的)原因(根本没有使用继承等)。如果不编写类,整个代码可能会简单得多,并且使用函数式编程方法很容易测试。这并不意味着类是坏东西,它们对于解决大多数大的和/或复杂的问题是必要的,但我总是发现它们被过度使用。

使用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]上可能有一个字符串作为元组,而tuple在计算距离时会忽略这一点。

这是真的,但是你的reflectx函数在这个问题上会怎么样——它会丢失额外的数据。我敢肯定,您可以想出一个解决方案,但我希望您看到,您所想到的对原始数据的更改和扩展越多,就越难设计出始终行为正确的数据类型。当您了解到现实应用程序的复杂性时,OOP就变得更加简单和健壮了,而以上只是使用OOP的原因之一。

如果我总结类"添加新函数(操作某些对象)或有效地更改对象结构"的需求,是否会遗漏一些内容?使用OOP的其他原因是什么?

除了可扩展性之外,OOP还有许多类似1的特性。组织:在代码中描述和定义数据和过程。2。状态:OOP帮助您定义和跟踪状态。三。封装:过程和数据存储在一起。4.继承:继承允许您在一个地方(在一个类中)定义数据和过程,然后稍后重写或扩展该功能。5。可重用性:所有这些原因和其他原因都允许代码具有更大的可重用性。面向对象代码允许您一次性编写实体(测试)代码,然后反复使用。

可以在类外部声明函数。但是在编程中,将它们存储在类中是一种更好的实践。OOP被认为更具可读性和可重用性。

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

类还允许您确定距离点的距离,而不是包含错误值(如两个以上坐标)的元组的距离。

我可以在距离函数中定义一个检查(使用if函数),如果前两个数据(在元组中)是整数,那么计算,否则显示一个错误。那我为什么要上课呢?

你举的一个例子对于证明类的使用是错误的。

类是描述事物的一种很好的方式,而不是操作数据。所以一个点只有两位信息来描述它(在二维空间中)。

想想更抽象的东西,比如电影文件。电影有各种各样的相关信息:标题,持续时间,流派,演员,年龄,流行度,语言,奖项…继续。尝试编写处理所有这些信息的长列表的函数,您将很快看到类的优点。

数学也许是一个没有那么多上下文信息的领域,只有几个变量,它们定义了一切。现实世界中的数据定义不太清楚,因此从类的可扩展性中获益。

你能详细描述一下你的第二段吗(一节课很好…)?如果没有太多的例子,我就无法清楚地理解这一点,而且我对Python还很陌生。

功能和面向对象编程是不同的范例。

在python中,一切都是一个对象,甚至是ints。整个语言都倾向于面向对象的编程,这就是为什么您应该选择它,特别是如果您的程序会增长的话。

您混合了函数式编程和命令式编程。函数编程并不意味着使用函数。你可以用python进行函数编程,但是他在文章中描述的方式是命令式编程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值