Python面向对象编程系列第一篇

一、类和对象

1、什么是类:

类是现实世界或思维世界中的实体在计算机中的反映,它将数据以及这些数据的操作封装在一起,类是抽象的。类只负责描述和定义对象的特征和行为,不负责调用代码。类同时也是创建实例的模板,而实例则是一个一个具体的对象。

2、什么是对象:

对象是程序运行时的实体,它的特征是存储在变量中的,行为是通过方法实现的,方法上操作对象的内部的状态,方法是对象对对象的通信的主要手段。类最基本的作用就是:封装代码。

3、实例化:

通过类生成对象的过程称之为实例化,而新创建的这个对象称为之这个类的一个实例。

4、一点小建议:

我们在写项目代码时,我们应该把每一个类放在一个模块中,然后把实例化和调用放在另一个模块中。从一个模块引入类的方式跟引入函数的方式相同。

二、方法和函数的区别

本质上说来,这两个是没有区别的,都是通过def关键字定义的。并且函数名和方法名都是代表了一块可执行程序的入口地址。

但如果要真的比较两者的区别:那么方法是设计层面的称谓,就像面向对象是一种设计思想一样,而函数是程序运行,过程式的一种称谓,再者就是如果是在类中定义的函数那么这就称为方法,如果是在模块中定义的,那么就是函数。

三、构造函数

1、什么是构造函数:

在python中,类中定义的 __init__叫做构造函数

2、构造函数的用途:

使你定义的类生成不同的对象,也就是初始化对象的特征。
如果没有构造函数,那么在人类的世界来看,生成的对象都是一样的,并没有什么特殊之处,但它们在计算机中的存贮是独立的,占用着不同的内存空间。
这里写图片描述

特点:
- 构造函数在实例化的过程中是自动调用的,但是它也是可以被直接调用的,通过下面这种方式:对象.__init__()
- 构造函数的返回值默认为None,我们不可以强制的指定它的返回值类型,如return 'student'会报错。

四、类变量和实例变量

类变量: 类变量是和具体的对象无关的,是抽象的概念。
访问方式:类名.变量名
类变量由于是一个抽象的概念,所以一定合理使用类变量,一个合理的使用场合就是定义一个用于计数的类变量,每生成一个对象,这个对应的类变量就自加1。
这里写图片描述

实例变量:在构造函数中,通过self和具体的对象绑定在一起的变量就是实例变量。实例变量是具有现实意义的,用于刻画对象的特征。
访问方式:对象.变量名
下面我们对一个错误进行分析,然后引出实例变量。
这里写图片描述
在上面的这个代码中,我们明明访问的是实例变量,但最终打印出来的确是类变量(AFeng)
这是因为我们传入的”AFeng”和18并没有把绑定到对象上,然后当我们在类的外部访问对象的属性时,python首先会在对象的实例变量列表中查找是否存在,如果不存在,并不会返回None,它会继续在类变量的变量列表中查找。所以我们访问时打印的是类变量的值。
这里写图片描述
下面我们来解决这个问题:
这里写图片描述
我们在这里通过self关键字把name和age属性绑定到了通过Student类生成的每一个对象上。这样就做到了定制化对象。

再次分析另一个错误案例:
这里写图片描述
这儿其实给我们造成了假象,其实是因为我们打印的实际上是传进去的参数。
修改下代码,如下所示:
这里写图片描述
立马就看到报错了,这是因为形参名变了,此时name在这里找不到了。但在上面我们说到过,根据变量搜索原则,变量列表中存在这个属性了,为什么没有去查找呢,这是因为这个访问是在内部进行的。变量搜索机制在类外部才会生效。

五、实例方法和类方法以及静态方法

1、实例方法:

由实例调用的方法,最大特点就是定义时需要传入一个self。
构造函数可以看做是一个特殊的实例方法,但它还是与实例方法有所区别的:
- 调用方式不同:构造函数是在实例化对象的过程中,由类自动调用的。实例方法是通过对象调用的。
- 意义不一样:构造函数用于初始化对象的特征,而实例方法用于操作对象的特征。

在实例方法内部调用类变量

  • 类名.类变量名(类外和实例方法中均可访问)
  • self.__class__.变量名(在实例方法中访问)

2、类方法:

@classmethod 
def plus_sum(cls):
    cls.sum += 1
    print(cls.sum)

类中的一个方法是一个类方法还是一个实例方法,取决于调用这个方法的主体,还有就是语法糖(@classmethod),不能只根据传入的形参self和cls来决定。
调用:
类名.方法名()
对象.方法名() 这个虽然可以调用,但不建议这么调用,但我很好奇这一点是怎么做到的。

作用:操作类变量,类方法不可以访问实例变量。

3、静态方法

定义:

@staticmethod 
def add(x,y):
    pass

最大的特点:没有任何强制传入的参数
静态方法可以访问类变量,通过类名.变量名的形式。但不可以访问实例变量,会报错。
对象和类都可以调用静态方法

对象.方法名
类.方法名

六、成员的可见性:也就是类中变量和方法的可见性。

1、方法的调用模式:

在类外调用:通过实例化的对象调用类中的方法。
在类中调用:一个方法中调用另一个方法。

2私有变量和私有方法的定义形式:

__变量名 和 __方法名
当我们给方法名加上__后,使之成为一个私有方法时,会报错。如下所示:
这里写图片描述

但是当我们把一个变量加上__后,访问时,并不会报错。
这里写图片描述
出现这个问题的原因是由于python动态语言的特性,当我们进行赋值操作时,动态的给student1对象添加了一个__name的属性。但是直接访问值时才会报错。
我们可以通过访问对象的变量列表来查看这一点。
这里写图片描述
在python中私有变量一般是直接访问不到的,但可以通过变通的方法,因为在python中,解释器会自动把私有变量转化为_类名__变量名
所以我们可以通过对象._类名__变量名访问类中的私有变量。所以严格意义上说,python中不具有私有变量这种机制。

六、面向对象的三大特性(继承)

继承:我们不去谈论继承的概念,只列举一些使用技巧。
在子类中调用父类的构造函数
这里写图片描述
通过父类.__init__(self, name, age)
这儿的self是必须传入的,因为我们构造函数是在实例化时自动调用的,因此self是由python解释器自动传入的,但在这里我们是显示的调用父类的构造函数,并且是通过类来调用构造函数的。所以self关键字是必须手动传入的。
这里写图片描述
这其实跟上面这种通过父类来调用构造函数的实质是一样的。
但这种调用父类构造函数的方法问题是很大的,如果我们在子类中使用了多次调用父类的方法。那么当我们的父类改变时,我们不得不改变大量的代码来满足我们的需求,这违反了软件开发中的开闭原则(对拓展是开发的,对修改是封闭的)
下面,我们来看第二种做法
这里写图片描述
当然上面的这种做法,不仅仅可以调用父类的构造函数,对于一般的函数也是可以调用的,另外,当子类的方法和父类的方法同名时,只会调用子类的方法,如果同名时,我们依然还想调用父类的方法,我们可以直接在子类方法中通过这种机制进行调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值