首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

python类学习笔记

今天开始就要学习面向对象编程了。这一块内容在python高级编程中经常会用到,也是跟别的语言风格不同的一点。之前也有接触过,理解的不好,再次学习,希望理解的透彻一些。

面向对象最重要的概念就是类(class)和实例(instance),必须牢记类是抽象的模板,就好比印刷机一样,类就是印刷机,实例就是被印出来的文档。也就是类创建出来的一个一个具体的「对象」。每个对象都拥有相同的方法,但各自的数据可能不同。

在python中,定义类是用class关键字的:

解释一下:

class后紧跟着类名,即Student,类名通常是大写开头的单词,紧接着是object,表示该类从哪个类继承下来的。通常,如果没有合适的的继承类,就使用object类,这是所有类最终都会继承的类。就是它们的父类。

创建实例:

可以看到,变量bart指向的就是一个Student实例,后面跟着的0x03106910是内存地址,每个object的内存地址都不一样。Student本身则是一个类。

可以自由的的给实例变量绑定一个属性,比如,给实例bart绑定一个name属性:

由于类可以起到模板的作用,因此,可以在创建类时,可以把一些我们认为必须要绑定的属性强制的填写进去,通过定义一个特殊的方法__init__方法,在创建类的时候就把name,score等属性绑定上去:

特殊方法「__init__」前后分别有两个下划线

注意到__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部就可以把各种属性绑定到self,因为self就指向创建的实例本身。

有了__init__方法,在创建实例的时候,就不能传入空参数了,必须传入与__init__方法匹配的参数,但是self不需要传,python解释器自己会把实例变量传进去。:

和普通函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是self,并且,调用时不用传递该参数。除此之外,类的方法和普通函数没有什么区别。所以你仍然可以使用默认参数,可变参数,关键字参数和命名关键字参数。

数据封装

面向对象编程的一个重要特点就是数据封装。在上面的Student类中,每个实例拥有各自的name和score这些数据,我们可以通过函数来访问这些数据,也就是在类的外面定义函数:

但是,既然Student实例本身就拥有这些数据,要访问这些数据,就没有必要用外部的函数来访问,可以直接在Student类内部定义访问数据的函数,这样就把数据封装起来了,这些封装数据的函数是和类本身是关联起来的,我们称之为类的方法。

要定义一个方法,除了第一个参数是self外,其他和普通函数一样,只需要在实例变量上直接调用,除了self不用传递外,其他参数正常传递:

这样一来,我们从外部看Student类,就只需要知道,创建实例需要给出name和score,而如何打印,都在Student类内部定义的,这些数据和逻辑被封装起来了,调用很容易,但却不知道内部实现的细节。

封装的另一个好处就是可以给Student类增加别的方法,比如get_grade:

总结:

类是创建实例的模板,而实例是一个一个具体具体的对象,各个实例拥有的数据都相互独立互不影响

方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据

通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部实现的细节。

和静态语言不同,python允许对对实例变量绑定任何数据,也就是说,对于两个变量实例,虽然他们是同一个类的不同实例,但拥有的变量名称都可能不同。

继承

面向对象的编程带来的好处就是代码的重用,实现这种重用的机制的方法之一就是通过继承机制。

当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(subclass),而被继承的类称为基类、父类或超类(base class、super class)

比如我们写一个类:

当我们要编写继承是就可以这样:

对于Dog和Cat来说,Kitty就是它们的父类,相对应的Kitty的子类就是Dog和Cat,这里注意观察Dog和Cat类后面括号里。

继承下来有什么用呢,最大的用处就是子类获得了父类的全部功能,这里好像我们自己继承老爸老妈的一些特征一样。

回到正题,由于Kitty实现了run功能,因此,它的子类什么也没干,就自动有了这个功能:

运行结果:

但是根据我们的意思,我们想要的是dog is run 和cat is run ,但是这里的结果好像并不是我们想要的。那怎么办,别急,可以在类的下面重新写方法:

这样再运行就得到了我们想要的结果:

但是,这样一来,我们在父类里有run方法,在子类里也有run方法,这种情况下,我们认为子类的run方法覆盖了父类的run方法,这样就是类的另一个好处,即:多态

理解多态,我们先来看一下数据类型。当我们定义一个类时,实际上就定义一种数据类型,这和我们定义python中普通的数据类型没什么两样。

在python中有一个函数isinstance() 用来判断一个变量是否是某一类型

再试试isinstance(c,Kitty)结果是True.有小伙伴在这里就犯迷糊了,其实仔细想想,这是有道理的,因为Dog是从Kitty继承下来的,当我们创建了一个Dog的实例C后,我们认为c的数据类型是Dog没错,但,同样的Dog本来就是Kitty的一种。

所以,在继承关系中,如果实例类型是某个子类,那它的数据类型也可以被看做父类的数据类型,反过来就不行。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180725G1T3DW00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券