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两列了。我从数据库中调数据,赋值给元胞数组变量。这样不就相当于“实例化对象”了么?至于针对这也对象的方法。我就编写特定函数来处理,实现我的目标就可以了。这样做相对于使用“类”有什么不方便的么?我体会不到。所以说是“非懂”
总之,在我看来类里定义属性就像创建变量。定义方法就像创建函数。类就是把这两者打包了。打包有什么好处?没体会。我就直接定义变量。针对变量编写函数。有什么不好?不知道。
————-以上之所以把我的思考过程写出来,是因为我的困惑来自于我固有的看法,其中可能包含不少谬误。放在这里可以使各位老师的指导更有针对性。
基本上, Python 中所有的东西都是物件, 函数是, 类也是, 类不同于其它物件, 是它可以用来实例化成一个又一个的物件, 该物件具有初始的某些属性, 其中也包括某些方法 (为了区分與函数的不同, 类的可调用属性, 称为方法, 而不是函数)
类的预设方法有很多, 比如以下各个属性, 其中
__init__
用来在类实例化时, 订定该实例的初始状态(属性), 另外设计者可以增加其他可调用的属性(方法), 当然也可以重新定义原有的方法, 包括所有的预设的方法.如果不考虑函数中, 利用别的类生成对象或更改对象属性, 函数当然不会去定义对象属性
类本身就是用来生成实例 (一个新的对象), 所生成的实例除了调用
__init__
初始的属性外, 其他会继承类中所定义的方法, 也会继承父类所定义的方法, 这些当然是用单纯的函数无法实现的 (非单纯的函数则有可能会实现的).函数与方法的差别在于, 前者以参数代入返回结果, 而后者则以实例为第一个参数, 通常在Python中, 以
self
来代表实例, 以cls
来代表类, 当然两者也可以用别的变量来表示. 既然所有的东西都是物件, 所以函数以及方法, 也都可以有属性.__init__
是Python中类实例化调用的预设方法, 用来定义初始的属性, 所以被视为定义属性, 而selfintro
基本上可能只在实例化以后才会调用的, 當然也可以在__init__
中被调用, 所以被视为定义行为, 原则上它们的差别只在于何时被调用.类是对一组函数的编排,函数序列操作同一批属性。区别无非就是类组合程度比函数高。对于简单逻辑,用类会将简单事情复杂化。但像一些大型的,需要n个函数甚至到模块级别组成一起解决逻辑,用类可以将复杂事情简单化,因为它可组织性,维护性更好。
类其实是对函数的一种抽象化,要知道无论哪种语言转换成机器语言之后就没有类的概念,函数也成了一段段跳转处理的代码。对于复杂程序不高的应用或需求来说,函数本身比类更好用,比如早期的DOS窗口游戏经常有大佬用几个十几个函数一个代码页写完的情况。但当程序或应用复杂度高了以后,单纯函数写作就有了一系列的问题,比如传参和判断过多,你一定用过linux命令行,有时一个命令后面跟上十几个参数来处理的,如果我们的程序要求处理的参数在几百到一千个左右会有什么情况?我的函数内部判断极其复杂,能够让任何检查代码的人脑袋爆炸。拿你举的机器人来做例子,我们有一个大脑发命令的函数,它控制机器人各部位运动,那么它本身需要知道机器人十几个关节的函数调用接口、每个接口对应可以执行的动作、执行时间等,一个简单的握拳动作就需要调用全部手指关节弯曲至最大。那么我要求机器人跳舞命令本身会需要前面的大脑命令函数做出多少判断?如果再联合机器人传感器进行状态判断,比如机器人现在脚部故障,该位置无法运动,跳舞时重心变化可能摔倒。那么单个函数的复杂度可能大到不可忍受。此时将机器人定义为一个类实例,将大量的参数比如手、手指、腿、脚等属性化,将大大减少函数的复杂程度,极大地方便复杂应用的实现。 类的继承说白了是一个偷懒的问题,同样以机器人举例,如果公司花了三年时间实现了前面的机器人,然而客户要求再生产一种人手改成无指手套的类似机器人,那怎么办呢?是重新开发一个?此时类的继承就发挥作用了,通过继承,我们可以保留第一种机器人的大部分特性而专注与手部的不同功能。 matab本身具有高级语言的特性,正如你所说的,它更多的是为了大规模运算做准备,依赖数据库,但做为编程语言本身需要考虑更多的问题,比如读写数据本身占用的资源开销大吗?实际上读写开销占用的是运行时间,这个指标重要度极高,远远超出类转函数编译时间的重要性。比如导弹锁定目标时间、机器学习时间等。