如有错误,欢迎留言指出讨论
1 面向对象和面向过程
1.1 面向过程注重的是结果,从结果出发去考虑问题的实现步骤。
1.2 面向对象注重的是设计,从现实生活的角度,从设计的角度去考虑问题的实现步骤。
1.3 虽然2种思想的目的都是为了做出一个程序,但是考虑问题的思想不一样。总之一句话:面向过程从结果出发考虑,面向对象以设计的角度解决问题。
1.4 使用情况:
· 对于一个小程序而言面向过程可能会更方便一点,可以很快捷的完成效果,面向对象反而会把简单问题复杂化,让初学者感觉很没必要。
· 对于一个大的项目而言我们不光看重的是程序结果,更看重的是程序的维护性和扩展性,保证这个程序不是一次性的程序,不是针对这一个功能而写的,最好保证这个程序将来使用的范围会更广,更好扩展。从这个角度考虑面向对象就更好一些了。
2 思想引入
2.1 问题1:
· 一辆车速度是60km/h,一条路总共1000km,请问多久可以走完。写出你的实现步骤。
· 你们肯定会这样写的,请看下方代码:
· 甚至会有人这样写,请看代码:
print(1000/60)
· 不管是第一种还是第二种做法其实都差不多,最终都能完成我题目的要求。但是这样写代码只能求出车速是60,路程是1000的用时,这段程序只能针对一个用户不适用于大部分的人,所以程序的扩展性很不好。其实这样写代码就是很明显的面向过程的思想,你的要求不就是要求出用时多久吗,只要我能完成结果即可,至于程序的扩展性我不考虑。以完成结果为目的,从结果出发考虑的问题,只要实现你的要求即可。
· 如果我想要扩展性比较好一点的程序,车速和路程是不固定的,是有客户来给定的,只要客户给出速度和路程我就可以求出时间这样的程序扩展性会不会好一点呢。应该如何实现呢?请看下方代码,可能有人会这样写:
· 上面这种做法是定义了一个函数,参数接收的是速度和路程,将来谁需要求时间只需要调用这个函数给出速度和路程即可,这样的话程序是不是就可以求出任意车速和路程的时间呢,拿这段程序和一开始写的代码作比较这段程序的使用范围是不是会更广阔一点。
· 其实上面的函数的做法就可以说是面向对象思想的体现了,将一段代码封装到一个函数中,将来这个功能可以重复的使用。这就是面向对象思想的第一个特征:封装。
2.2 问题二:
· 从这个程序可以看出虽然函数可以对一段代码进行封装,但是可能多个事物我们可能会写相同的函数,把不同的事物的代码全部写在一块可能会很乱,并且找起来也不方便。如果有一个容器里面可以封装很多的函数和变量的话这样我们管理起来是不是就很容易了。
· 在程序中可以封装很多函数和变量的就是类,关键字是class。
3 如何写一个类
设计一个植物大战僵尸的程序。请写出你的实现思路。
· 类中可以写很多的函数和变量,写在哪个类中的函数就只有自己可以使用,别的类是不能够使用和访问的。
· 类是用来描述一类事物的。一个事物是由属性和行为构成的。所以类就是由属性和行为构成的。属性指的就是一个事物的信息,比如人的姓名、年龄等,桌子的长、宽、高、颜色等都属于信息,一般叫做属性。行为就是这类事物会做什么事情,他有哪些功能。在程序中属性用变量表示,行为用函数表示,所以类是由变量和行为构成的。
4 如何使用类(创建对象)
4.1 创建对象
· 要访问类中的函数或者变量必须先创建对象才可以。
· 创建对象格式:
5 类和对象的关系
5.1 类:
· 类就相当于一个图纸,相当于一个模板,在这张图纸上规定这件事物的特征和行为,是一个比较抽象的东西。作用就是为了创建对象使用的,在类中规定这个对象有哪些特征和行为。
5.2 对象:
· 对象就是根据类(图纸)创建出的一个具体的东西,可以看得见摸得着真是存在的一个物品。拥有这个类所有的属性和方法。
5.3 提问:
· 先有类还是先有对象?
先有类
· 一个类可以创建几个对象?
无数个
· 对象和对象之间的属性是一样的吗?
是的,因为类是一组具有相同属性和相同操作的对象的集合,类中的每个对象都是这个类的一个实例
6 小结:
1) 面向对象注重的是设计,从设计、现实生活的角度考虑问题。面向过程注重的是结果,只要完成结果即可,至于过程和以后的扩展性、维护性、适用范围这些问题不考虑。
2) 一般对于小程序面向过程会更简洁一点,对于大型的项目面向对象会好一点,将来的维护、扩展都很方便。目前我们接触的都是一些小程序你们可能会觉得用面向对象太麻烦,多此一举。
3) 类是用来描述一类事物的,比如桌子、人、动物等,事物的属性我们一般在类中写成变量,行为我们写成函数,或者也有人叫做方法。
4) 类就相当于一张图纸,一个模板,是一个比较抽象化的概念,定义了这类事物的属性和行为。对象就是根据类创建出来的具体事物,拥有这个类所有的属性和方法。
5) 一个类可以创建出很多的对象,对象与对象之间的值是不一样的。
6) 面向对象其实就是对功能进行封装。
7) 主要任务:根据要求会创建类和对象
8 构造函数
8.1 作用:
1) 初始化赋值用的
2) 创建变量使用的
3) 通过self.变量名就会创建出变量,这种才是创建类变量的正确写法。
4) 创建对象的时候会自动调用调用构造函数。
5) 创建对象,类名后面的小括号一定不能忘记。
8.2 self
1) self代表当前对象,谁调用self就代表谁,这个单词是自己的意思。
2) self不是关键字,也可以换成其他名字,但是我们一般都用self。
9 练习:
9.1 2只手交换卡牌
· 先分析有哪些对象
· 再分析有什么类
· 接着分析每个类有什么属性和行为
10 总结:
10.1 掌握面向对象和面向过程思想上的区别
10.2 对于你们目前而言面向对象思想就是对代码的封装,封装就是面向对象思想的第一特征的体现
10.3 掌握如何创建类和对象
10.4 掌握类和对象的概念
10.5 掌握构造函数和self的使用
10.6 能理解2只手交换卡牌的案例
第一单元: 面向对象(二)
1 析构函数
1.1 __del__()
· 在对象销毁的时候自动执行的。
1.2 对象销毁时间:
· 程序执行完毕自动销毁
· 自己手动销毁,用del可以销毁
· 如果变量写在函数内部,那么函数执行完毕,变量会自动销毁
· 注意:对象销毁了就不能再次使用了。再次使用会报错
2 重写__str__()和__repr__()函数
2.1 __str__():
· 在打印对象名字的时候会自动执行的函数,这是一个内置函数,底层提供给我们的。
· 默认这个函数会打印出这个对象的地址值。
· 如果不想让他打印出地址值可以重写函数,其实就是写一个一模一样的把底层的覆盖掉。
· 一般重写__str__()是为了打印变量信息使用的
· 注意:打印对象名的时候会自动调用这个函数。下面打印p1和p2是一个意思,都像予调用了__str__()函数。
2.2 __repr__():
· 和__str__()函数是一个意思,作用是一样的,调用时间也是一样的。
· 当str不存在的时候才会执行repr函数,如果2个函数都在执行的是str函数。
3 访问限制
3.1 目的:
· 防止别人随意修改
3.2 做法:
· 哪个变量或者函数不想让别人访问或者修改就在名字前面加2个下划线。
· 加上2个下划线之后只有自己可以访问,别人是访问不到的。
3.3 getXX和setXX:
· 既然自己可以访问,那如果非得访问就给他提供对应的访问方法即可,访问一般用get来命名:
· 要赋值可以提供间接的对应的赋值函数,函数名字一般叫做setXXX。
3.4 get和set做法的意义:
· 一般情况下写set赋值函数都会在函数内部做一个数据过滤,比如age本不可赋值为负数,我们可以在函数内对age的值进行一个判断,合法再赋值给age不合法给用户一个提醒。做法如下:
3.5 访问限制的好处:
· 做到数据过滤,不让别人随意的修改值。
4 继承
4.1 概念:
· 继承就是子承父业,儿子拥有父亲的所有东西。
· 在程序中也可以继承,子类继承父类,子类就拥有了父类所有的属性和方法,减少了代码量。
4.2 什么情况下使用继承:
· 当多个类出现相同的代码
· 满足is a,谁是谁的一种条件
· 当同时满足上述2种条件即可使用继承。
· 比如猫是动物、狗是动物,并且猫狗中都出现相同代码的时候我们可以抽象出一个父类动物类出来,把相同的代码写在动物类中,让猫和狗继承自动物类。代码不需要重复编写。
4.3 如何使用继承:
4.4 继承的优点:
1) 减少代码量,提高代码的复用性。
2) 多态的前提。
4.5 继承的缺点:
1) 耦合性增强
2) 代码的设计原则要求:高内聚,低耦合,简言之就是自己的事情自己做,类与类之间尽量产生少的联系。
4.6 多继承:
1) 一个子类是可以直接继承多个父类的,父类之间通过逗号隔开。
2) 当2个父类中出现同名的方法默认调用的是排在前面的父类的。
4.7 继承中构造函数的问题
1) 当父类构造函数有参数的话子类必须给父类构造函数中的参数赋值。
2) 当父类构造函数无参的话子类最好也调用一下父类的构造。不调用的话会出警告。可能会出现问题。
3) 调用父类构造函数,可通过super调用,super就是父亲的意思。
super(Student,self).__init__(name,age)
4) 当用的是多继承的话调用父类就不能使用super了,因为不知道指的是哪个父亲了,所以用类名调用即可。
Person.__init__(self,name,age)
4.8 继承的重写问题:
5 总结:
5.1 掌握访问限制
5.2 掌握继承的使用
5.3 掌握构造函数的重写和普通函数的重写
第二单元: 面向对象(三)
1 多态
1.1 概念:
· 一种事物的多种形态。
1.2 表现形式:
· 父类对象=子类()
1.3 尝试完成下方的题目:
2 其实python没有严格意义上的多态。
3 限制添加实例的属性
4 @property
为了解决上面的问题,我们将属性设为私有提供get和set
上面这种方式虽然安全了,但是看着不太爽,就想用以前的方式点出来怎么办。
5 运算符重载:
上图中对象相加会出现报错的现象,不想让他报错,就想让2个对象相加求出2个num相加之和怎么办。
运算符重载的函数都有: