Python 中的类和函数的区别是什么?

老师说:类是用来高效管理属性代码和行为代码的。类就相当于是对一个或多个函数的封装

class People:
def __init__(self,N,A):
self.name = N
self.age = A
def selfintro(self):
print(f'大家好,我叫{self.name},今年{self.age}岁。')

P1 = People( 'Jack',12)
P2 = People( 'Paul', 11)

P1.selfintro()
P2.selfintro()

关于上面这段代码,有几个问题。
1 、def init(self,N,A):这一段主要是定义对象属性。类和函数的主要区别就是类可以定义对象属性?进而可以 Jack = People( ‘Jack’,12)来方便的实例化一个对象。使它也有相同“格式”的属性?这一点用单纯的函数绝对无法实现的么?
2 、老师说这一段 def selfintro(self): 是在定义行为。但是我的感觉就是在类里面嵌套了一个函数。然后是你可以在外面针对同一类对象调用这个函数,例如:P1.selfintro()。感觉这部分和函数调用没有任何区别,我理解对么?
3 、为什么 def init(self,N,A): 这一段就是定义属性,而 def selfintro(self):就是定义行为。python 解释器是怎么知道前一个是定义属性?后一个是定义行为?两句都是 def 开头的啊。是因为init这个函数就是python定义属性专用的自带函数么?

————2022年7月9日14:14更新—————
看了很多不同论坛的回复,很有启发。也反思了一下自己的困惑到底是什么?
本人非计算机专业,入门语言是大学学的C语言。于是形成了一种惯性思维,什么都可以用函数解决。
看了python入门书,当中提到了类,面向对象。同时也参考了一些介绍面向对象编程的视频,文章。看后感觉似懂非懂。

所谓“似懂”:我能看懂创建一个类,大致分两部分。
1、定义属性:似乎是做了一个数据模板(好比是做糕点的模具、也可以看作做了一个标准化的机器人)。
2、定义方法:针对上面的机器人定义了一些针对机器人的命令,使机器人可以完成特定动作。跳,走。蹲……

实例化一个对象,好比用糕点模子拍面团。这样可以批量标准化的做出一样的糕点。也可以说批量化生产出一堆机器人。这些机器人诞生之日就可以自动支持标准指令(类中已经定义好的方法)。

所谓“非懂”。你非让我用“类”去编程,我也可以。但我感觉我在邯郸学步,只是做形式上的模仿,并没有体会到“类”的优点,便利。(之所有说优点,便利。是因为有人告诉我面向对象编程处理的问题,面向过程也都能解决。只是特定问题面向过程不如面向对象方便。)就是我觉得就用变量+函数,也可以实现上述效果。所以就会产生疑问,这地方为什么要用类,然后层层继承。看着眼晕。
类,似乎创建了一个私有的变量类型(定义属性)。且我为这个私有变量类型创建了特定的函数,即方法。
那我不用“类”这个工具,我以后创建同样类型变量的时候Ctrl+c Ctrl+v一下不就可以了。
另外类创建了一个模具可以批量的创建同样的私有变量(也就是实例化对象)。但是我真要批量的用类似“P1 = People( ‘Jack’,12)”来实例化对象。也不会一行一行去手工敲代码。应该也是用循环语句或条件语句来创建吧。
考虑到一般大量的数据是放在数据库中的,完全可以通过给变量批量赋值来实现“类”批量制造标准的“私有变量类型”的目的。即通过赋值完成变量格式的定义。matlab中有一种叫元胞数组的变量。它每个单元既可以装字符串,也可以装数值(整数,浮点都可以)。非常灵活。以上面的代码为例。我不用事先定义一个people类。数据在数据库中已经有name、age两列了。我从数据库中调数据,赋值给元胞数组变量。这样不就相当于“实例化对象”了么?至于针对这也对象的方法。我就编写特定函数来处理,实现我的目标就可以了。这样做相对于使用“类”有什么不方便的么?我体会不到。所以说是“非懂”

总之,在我看来类里定义属性就像创建变量。定义方法就像创建函数。类就是把这两者打包了。打包有什么好处?没体会。我就直接定义变量。针对变量编写函数。有什么不好?不知道。

————-以上之所以把我的思考过程写出来,是因为我的困惑来自于我固有的看法,其中可能包含不少谬误。放在这里可以使各位老师的指导更有针对性。

讨论数量: 6
Jason990420

基本上, Python 中所有的东西都是物件, 函数是, 类也是, 类不同于其它物件, 是它可以用来实例化成一个又一个的物件, 该物件具有初始的某些属性, 其中也包括某些方法 (为了区分與函数的不同, 类的可调用属性, 称为方法, 而不是函数)

类的预设方法有很多, 比如以下各个属性, 其中__init__用来在类实例化时, 订定该实例的初始状态(属性), 另外设计者可以增加其他可调用的属性(方法), 当然也可以重新定义原有的方法, 包括所有的预设的方法.

>>> object
<class 'object'>
>>> for attr in dir(object):
...     print(attr)
...     
__class__
__delattr__
__dir__
__doc__
__eq__
__format__
__ge__
__getattribute__
__gt__
__hash__
__init__
__init_subclass__
__le__
__lt__
__ne__
__new__
__reduce__
__reduce_ex__
__repr__
__setattr__
__sizeof__
__str__
__subclasshook__


类和函数的主要区别就是类可以定义对象属性?

如果不考虑函数中, 利用别的类生成对象或更改对象属性, 函数当然不会去定义对象属性

使它也有相同 “格式” 的属性?这一点用单纯的函数绝对无法实现的么?

类本身就是用来生成实例 (一个新的对象), 所生成的实例除了调用__init__初始的属性外, 其他会继承类中所定义的方法, 也会继承父类所定义的方法, 这些当然是用单纯的函数无法实现的 (非单纯的函数则有可能会实现的).

感觉这部分和函数调用没有任何区别,我理解对么?

函数与方法的差别在于, 前者以参数代入返回结果, 而后者则以实例为第一个参数, 通常在Python中, 以self来代表实例, 以cls来代表类, 当然两者也可以用别的变量来表示. 既然所有的东西都是物件, 所以函数以及方法, 也都可以有属性.

python 解释器是怎么知道前一个是定义属性?后一个是定义行为?两句都是 def 开头的啊。是因为 __init__ 这个函数就是 python 定义属性专用的自带函数么?

__init__是Python中类实例化调用的预设方法, 用来定义初始的属性, 所以被视为定义属性, 而selfintro基本上可能只在实例化以后才会调用的, 當然也可以在__init__中被调用, 所以被视为定义行为, 原则上它们的差别只在于何时被调用.

Amber
函数是做特定的事情,类则是特定的事情。

类通常具有方法,这些方法是与特定类相关联的函数,并执行与该类的事物相关联的事情 - 但如果您只想做某事,那么您只需要函数。

本质上,类是将函数(作为方法)和数据(作为属性)分组为围绕某种事物的逻辑单元的一种方式。 如果您不需要该分组,则无需创建类。

Bob Belderbos
当人们来到 Python 时,他们遇到的一件事情就是 OOP(面向对象编程)。与其说是类的语法,不如说是何时使用它们以及何时不使用它们。

类非常有用且强大,但您需要知道何时使用它们。以下是一些注意事项。

1. 你需要保持状态

例如,如果您需要管理一群学生和成绩,或者当您构建一个记录动作、得分等的游戏时。基本上,当您拥有数据和行为(变量和方法)结合在一起的时候,您将使用一个类。

2. 更大的项目——类有利于代码组织和可重用性

比如运载工具类的例子:
运载工具包括货车、自行车、机动车辆(摩托车、汽车、卡车、公共汽车)、轨道车辆(火车、有轨电车)、船只(轮船、轮船)、水陆两用车辆(螺旋推进车辆、气垫船)、飞机(飞机、直升机)和宇宙飞船。

当您看到这样的层次结构时,使用类可以带来更好的代码组织、更少的重复和可重用的代码。

如果您有数百个子类并且需要进行根本性更改,这将变得特别强大。您可以在基类(父类)中进行一次更改,所有子类都会接受更改。

注意:虽然我喜欢继承,但组合通常是首选,因为它更灵活。

3. 封装

您可以分离内部和外部接口,隐藏实现细节。您可以更好地隔离或保护您的数据,只为我们类的对象提供某些访问权限。

这就像驾驶汽车而不必了解机械原理。当我启动我的汽车时,我可以使用我知道并且应该使用的通用界面进行操作:油门、刹车、离合器、方向盘等。我不必知道发动机是如何工作的。

您的类也可以向设计者隐藏这种复杂性,这使您的代码更易于理解(优雅)。

这样做的另一个主要好处是所有相关数据都被组合在一起。提到 person.name, person.age, person.height 等。想像一下,必须将所有这些相似的数据保存在单独的变量中,它会很快变得混乱和无法维护。

更好地理解 Python

Python 中的一切都是对象。了解类和对象可以让您更好地准备使用 Python 的数据模型和完整的功能集,这将导致更干净和更“pythonic”的代码。

Python 数据模型,它描述了您可以用来使您自己的对象与最惯用的语言功能良好配合的 API。您可以将数据模型视为将 Python 描述为一个框架。它形式化了语言本身构建块的接口,例如序列、迭代器、函数、类、上下文管理器等。最后,很多重要的设计模式都是从 OOP 中汲取的。

主要重点

如果您需要保持状态,类非常棒,因为它们将数据(变量)和作用于该数据的行为(方法)容器化,并且在逻辑上组合在一起。

这导致代码组织得更好(更干净)并且更容易重复使用。

避免使用类

话虽如此,OOP 并不总是最好的解决方案。以下是避免使用类的一些想法:

  • 最直接的原因是如果你的类只有一个构造函数和一个方法。然后只需使用一个函数
  • 小型(一次性)命令行脚本可能不需要类。
  • 如果您可以使用上下文管理器或生成器来完成相同的任务,那么这可能会更简洁且“Pythonic”。
1年前 评论
Jason990420 (作者) 1年前
kakabobo (楼主) 1年前
kakabobo (楼主) 1年前
pardon110

类是对一组函数的编排,函数序列操作同一批属性。区别无非就是类组合程度比函数高。对于简单逻辑,用类会将简单事情复杂化。但像一些大型的,需要n个函数甚至到模块级别组成一起解决逻辑,用类可以将复杂事情简单化,因为它可组织性,维护性更好。

1年前 评论

类其实是对函数的一种抽象化,要知道无论哪种语言转换成机器语言之后就没有类的概念,函数也成了一段段跳转处理的代码。对于复杂程序不高的应用或需求来说,函数本身比类更好用,比如早期的DOS窗口游戏经常有大佬用几个十几个函数一个代码页写完的情况。但当程序或应用复杂度高了以后,单纯函数写作就有了一系列的问题,比如传参和判断过多,你一定用过linux命令行,有时一个命令后面跟上十几个参数来处理的,如果我们的程序要求处理的参数在几百到一千个左右会有什么情况?我的函数内部判断极其复杂,能够让任何检查代码的人脑袋爆炸。拿你举的机器人来做例子,我们有一个大脑发命令的函数,它控制机器人各部位运动,那么它本身需要知道机器人十几个关节的函数调用接口、每个接口对应可以执行的动作、执行时间等,一个简单的握拳动作就需要调用全部手指关节弯曲至最大。那么我要求机器人跳舞命令本身会需要前面的大脑命令函数做出多少判断?如果再联合机器人传感器进行状态判断,比如机器人现在脚部故障,该位置无法运动,跳舞时重心变化可能摔倒。那么单个函数的复杂度可能大到不可忍受。此时将机器人定义为一个类实例,将大量的参数比如手、手指、腿、脚等属性化,将大大减少函数的复杂程度,极大地方便复杂应用的实现。 类的继承说白了是一个偷懒的问题,同样以机器人举例,如果公司花了三年时间实现了前面的机器人,然而客户要求再生产一种人手改成无指手套的类似机器人,那怎么办呢?是重新开发一个?此时类的继承就发挥作用了,通过继承,我们可以保留第一种机器人的大部分特性而专注与手部的不同功能。 matab本身具有高级语言的特性,正如你所说的,它更多的是为了大规模运算做准备,依赖数据库,但做为编程语言本身需要考虑更多的问题,比如读写数据本身占用的资源开销大吗?实际上读写开销占用的是运行时间,这个指标重要度极高,远远超出类转函数编译时间的重要性。比如导弹锁定目标时间、机器学习时间等。

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!