二十二·面向对象

这一节超级重要,但是只总觉得自己讲的不好,希望大家包涵,然后提出一些意见


面向过程

之前我们讲的所有代码,其实都是面向过程的。

什么叫面向过程呢?

面向过程是一种以事件为中心的编程思想编程的时候把解决问题的步骤分析出来,然后用函数把这些步骤实现,在一步一步的具体步骤中再按顺序调用函数


面向对象

在解决比较小的需求和问题的时候,使用面向过程,一步一步来处理的话,还是比较容易的。

但是当我们的需求和问题非常大的时候,再使用面向过程,我们的步骤就越来越繁琐,很容易出错。

这个时候,我们把具有相同性质的内容聚合到一起,形成一个对象,对象内部包括了它的属性和形为,然后我们就把一个很大的问题,抽象成了几个对象之间的交互。

比如我们去民政局办理结婚的时候,这是一个比较小的问题,那么我们面向过程就可以解决,步骤就是:

  1. 拿户口本和你对象一起去民政局
  2. 签写东西,拍照
  3. 拿到证件

这样就完成了。

可是当我们准备开一个饭店的话,这样就很麻烦了,我们要去办各种证件,做很多事情。那么我们就使用面向对象的思维来讲:

  1. 将政府部分形成一个政府对象,这个对象能办证,允许你开店
  2. 将员工部分形成一个员工对象,这个对象分不同的类型,可以跑腿,可以炒菜,可以打理店铺等
  3. 将房屋中介物业形成一个物业对象,这个对象可以租房,交租,办水电之类的

现在有了这三个对象,我就可以先把自己当成一个对象——店主

  • 店主与物业对象交互,把店铺定下来
  • 然后去跟政府对象交互,进行办证之类的
  • 最后跟员工对象交互,雇佣员工进行工作

你看,把一个很大的问题,抽象成一些对象后, 就简单了很多。


类与对象

类的定义——在代码中,我们将具有相同行为和属性的概念都聚合到一起,形成了一个代码单元,叫类。

类是概念性的东西,不能当作变量直接使用。

那么我们如何使用这个类呢?

我们可以声明一个变量,然后将类赋值给它。这个过程叫实例化,这个变量我们可以叫它对象或实例

刚才我们在类的定义中说到,类中是有行为和属性的,转换成代码语言就是,行为用函数来表示,属性用类变量来表示,通常我们还是叫它为属性。

类的定义语法如下:

我们现在定义一个简单的类,动物类:

  • class是创建类的关键字
  • Animals是我们创建的类的名字
  • class_name是我们定义出来的类变量
  • print_info是我们定义的类函数
  • 需要注意的是,类函数的第一个参数,一般都是self,这个self是代表着类的实例,在实例对象调用这个函数的时候,会把自己自动代入到这个self中去。(如果你不理解的话,就把这个当成规矩

现在我们已经完成了这个类,那么我们如何去使用呢?看下面的例子:

我们实例化了一个对象animal,将Animals类实例化给了它。

然后使用这个对象去调用了类变量和类函数。

结果如下:

animals的类变量为Animals

This class name is Animals

animals的类函数为True

可以从结果看到,我们打印了类变量,显示的是我们在类中定义好的内容。

然后我们调用了类函数,这个时候,我们的代码会先去类函数中执行定义好的print函数,然后把True返回回来,所以我们打印出来的类函数为True。

我们还可以再定义一个类函数,加上一些参数:

结果为:

animals的类变量为Animals

This class name is Animals

animals的类函数为True

animals有参数的类函数为3

从上面的两个例子中,我们可以看到,如果我们想要调用类函数的时候,只需要使用实例化出来的对象去调用就好了,self这个参数我们可以不去指定,就可以使用。


类变量的修改

如果我们想要去修改类变量的话,你会如何去做,是这样吗?

结果为:

Animals

Animals

按照我们的想法,我们在bbb的对象中,应该已经改变了类变量class_name的值,为什么最后打印出来的还是Animals呢?

我们之前有说过,类是一个概念性的东西,我们在这个例子中创建的类变量class_name是属于类的,你如果想要使用对象去修改属于类的东西,这是行不通的!

我们只能做一些修改,让对象去修改属于他自己的那一部分变量。如下:

结果为:

Animals

bbb

Animals

可以看到,我们对类做了一些修改,在change的类函数中,在class_name前面加上了self.  这样做的目的是为了,让对象在修改变量的时候,不是去修改类本身代表的概念性变量,而是自身实例化自类的变量。

我们先打印了一下aaa对象的class_name,发现是Animals

我们修改了一个bbb对象的class_name,然后打印发现是修改后的bbb

我们又打印了一下aaa对象的class_name,发现还是Animals

这是为什么呢?

类只有一个,可是对象可以实例化出无数个,对象之间在一般情况下,是不互不干涉的,你修改了自己的东西,不会影响到别人。所以我们修改了bbb对象的变量,不会影响到aaa对象。

在本例中,change函数中,我们主要是修改了self的class_name变量,之前我们也说过self是代表对象的,所以我们在一个对象中去修改对象本身的变量,更不会影响到另外的对象

那么如果我们想要修改类的变量呢?不单单是修改一个对象的变量呢?想要修改一下类的变量,可以让所有的对象都能得到改变,如何做呢?

结果为:

Animals

bbb

aaa

从结果中我们可以看出,我们使用了Animals.class_name = "aaa",去修改属于类的class_name变量,然后在对象中,相应的class_name也跟着改变了。

那么,如果以后我们想要一个所有对象都能共享的变量,就使用这种方式去声明变量,然后用类的名字调用这个变量去修改。

如果只是想修改一个对象的变量,就使用self去调用修改这个变量,不会影响到其它的对象


类的构造方法

之前我们实例化对象,都是使用类的名字来实例化,如animal = Animals()

所有的对象都是一样的,那么假如我们想在实例化的时候,就传入一些参数,让对象与众不同呢?

结果为:

My Name is 小红

My age is 8

我们新建了一个类,叫People。里面有一个带参数的构造函数__init__,每次在实例化的时候,都会自动调用这个函数,这样我们在实例化的时候,传入的参数会自动赋值给self。

先说明一点,只要是函数名前后都带有两个下划线的,都是类专有方法。专有方法有很多,可以私下了解,主要使用的就只有这一个函数

我们在实例化的时候,就把参数传入了进去,然后直接调用类函数print_name和print_age,就可以得到结果,确实是我们刚才传入的数据。

如果有时候我们不想传参数,有时候想传参数了怎么办?那么就使用默认参数来解决。

结果为:

My Name is 小红

My age is 8

My Name is 默认

My age is 111

我们在init函数中,使用了默认参数,那么当我们实例化的时候,没有传入参数的情况下,就会直接使用默认参数的内容展示。如例子中的xiaoming。


类的私有方法和变量

有的时候,我们不想让别人知道我们的类中定义有哪些变量,有哪些方法,我们就可以把这些变量和方法定义成私有变量和私有方法。

结果为:

My Name is 小红

Traceback (most recent call last):

 File "C:/Users/xxx/PycharmProjects/NewProject/T.py", line 17, in

xiaohong.print_age()

AttributeError: 'People' object has no attribute 'print_age'

在例子中,我们定义了两个私有变量,一个私有函数。私有的都以两个下划线开头

我们再去调用私有的东西时,就会报错,说找不到类中有此函数或变量。


继承

类的一大特性就在于继承。

继承是什么呢,就是我们定义好了一个A类,我们可以在创建B类的时候,让B类去当A类的子类,那么A类就是B类的父类。

子类就可以继承父类中所有非私有的方法和变量,也就是说,父类中私有的东西,子类是不能继承的。

类继承的语法为class 类名称(继承类)

结果为:

My Name is 默认

Traceback (most recent call last):

 File "C:/Users/xxx/PycharmProjects/NewProject/T.py", line 19, in

worker.print_age()

AttributeError: 'Worker' object has no attribute 'print_age' 

在本例中,我们创建了People类,有一个私有的函数,一个公有的函数,两个公有属性。

我们又创建了一个Worker类,然后继承了People类,这个类里什么都没有。

然后我们用Workder类实例化了一个worker对象,然后去调用print_name,发现可以打印出信息。

再去调用print_age的时候,发现报错了。

类的继承,方便了我们去把问题抽象出来,抽象出不同的类,分有层次,有更好的逻辑性。


重写

直接举例来说明

结果为:

My Name is 默认!!!!!!!!!

My age is 111!!!!!!!!!

My Name is 默认

My age is 111

可以看到,我们在子类中,写了一些跟父类中相同名字的函数,这就叫重写。

我们分别初始化了一个父类对象和一个子类对象,分别去调用同样的函数。

从结果上来看,父类对象只调用了自己的函数,子类对象也只调用了自己的函数。

如果我想在子类中,去调用父类的函数呢?

结果为:

My Name is 默认

My Name is 默认!!!!!!!!!

My Name is 默认

My age is 111!!!!!!!!!

我们在子类的函数中,使用super()来代表父类对象,然后用super()去调用了相应的父类函数。

从结果上来看,确实是先打印了父类的函数,再调用了子类的函数。


一个类也可以继承多个类,需要注意括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索:即方法在子类中未找到时,从左到右查找父类中是否包含方法


类具有三大特性:

封装:类中封装了变量和方法

继承:子类继承父类

多态:子类可以使用同样的函数名来重写父类的函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值