目录
零、前言一、面向对象编程(一)概念理解二、类和对象的概念(一)面向对象的两个重要概念类和对象。(二)类的解释1、创建类2、类属性(区别于下面的对象属性)(三)对象的解释1、创建对象2、对象属性(四)self是什么?三、面向对象编程的三大特性(一)封装1、封装含义:2、封装公有和私有(二)继承继承的含义:(三)多态多态的含义:零、前言
最近在深入学习python的进阶课程,学python也有两三年了,由于是业余时间学习,也没有报班,全靠网上资料自学,所以现在想沉淀一下python的基础和进阶知识,做一个记录,有错误的尽可指出。
一、面向对象编程
(一)概念理解
这个整得我不会了,非计算机科班出身,刚开始理解起来,简直无法转换思维,下面说一下我的理解:
我是将面向对象和面向过程两种编程思想结合起来理解的。面向对象这个编程思想就像是将你编好的程序变成一个功能块一样,不需要你一步一步的去编写实现这个功能的过程。
举个栗子来理解一下,以家务活拖地为例子
人工拖地的过程一般是这样子,先用扫把扫一遍 > 装一桶水 > 拿拖把 > 拖把浸湿 > 拧微干 > 来回拖地 > 直至拖完。
这就是一种面向过程的编程思想了,每一个环节都不能出错,不然你就等着老婆骂吧。
而面向对象编程思想就不太一样了,就是:买一个扫拖机器人 > 插电 > 按开始键 > 等待拖完地,你不需要知道机器人是怎么扫地怎么拖地的,只要地板够平整,环境允许,调用开关就行了。我还是买台机器人吧。。。
二、类和对象的概念
当你开始理解对象的时候,你会发现世界在你看来都可以是对象,所以才有“万物皆对象”的说法。你的书籍,不需要你去写书;你的Siri,不需要你去造一个;你的电子表,不需要你去生产一个。理解到这里,相信你已经有一个“对象”的概念了。😜 😝
👇继续往下看。
(一)面向对象的两个重要概念类和对象。
拿上面拖地的例子来说,那个拖地机器人就是对象,而生产拖地机器人的图纸就是类了; iphone手机上的Siri,每一台iPhone在刚买到的时候,都是一个原装的Siri,没有带有任何个人特征(比如你的声音),当你初始化后,然后你手机的Siri就变成你专属Siri(只能识别你的声音)。
类可以创造很多差不多的对象。在python中,变量,列表,函数,元组都是对象。
(二)类的解释
我们说类是生产对象的模板,类是一个抽象的事物,而对象是类的具体化。简单来看,类 = 属性 + 方法
撰写格式:
1、创建类
class 类名:属性1 = xxdef 方法1:print('正在调用方法1')
🌰举个栗子,创建一个狗类:(并说明创建类的一些规则)
class Dog: # 类名首字母是大写,一定是大写是为了区分函数做的规定。attribute = '四条腿,一条尾巴' # 所有狗类都有的属性def eat(self): # 所有狗类都有的方法print('正在吃东西....')>>> dog1 = Dog() # 这个动作叫做实例化 一个对象>>> dog1.attribute # 调用属性不需要加括号'四条腿,一条尾巴'>>> dog1.eat() # 调用方法需要加括号正在吃东西....
从上面例子来看,狗类Dog的属性“attribute”,狗类的方法“eat(self)”,这些都属于类属性和方法,它们的关系如下:
2、类属性(区别于下面的对象属性)
类属性就是每一个对象被实例化后都会有的属性,拿上面的例子来说,不管狗类实例化成dog1,dog2,dog3,都会有 **“attribute”**这个属性,是所有实例化狗共有的。
类属性的修改,只能通过类名.属性1 = XXX的方法修改。
class Dog:attribute = '四条腿,一条尾巴' # 类属性def eat(self):print('正在吃东西....')>>> dog1 = Dog()>>> dog1.attribute'四条腿,一条尾巴'# 修改实例化对象的类属性,不改变原始类Dog的attribute>>> dog1.attribute = '两只眼睛'>>> dog1.attribute'两只眼睛'>>> Dog.attribute'四条腿,一条尾巴'# 通过**类.属性1 = XXX**修改类属性,不影响已经实例化对象dog1的attribute>>> Dog.attribute = '两只耳朵'>>> dog1.attribute'两只眼睛'# 重新实例化一个dog2,那么它的属性就已经修改>>> dog2 = Dog()>>> dog2.attribute'两只耳朵'
(三)对象的解释
对象,就是类实例化后的对象,也就是类的具体化实体,同时对象也满足对象 = 属性 + 方法。拿上面狗类的例子来说,dog1、dog2都是属于对象。
1、创建对象
class Dog:attribute = '四条腿,一条尾巴' # 类属性def eat(self):print('正在吃东西....')# 创建一个dog1的对象>>> dog1 = Dog()以下这种操作不是创建对象>>> dog1 = Dog # 这个操作意思是给Dog类创建了一个新的别名,其实dog1本质还是一个类,并不是实例化对象。
2、对象属性
对象属性的意思是:这个属性只是属于实例化对象的,属于对象的,对象属性的格式是 :self.属性1 = XXX。类是不能直接调用对象属性,需要用类名().属性1调用。
🌰举个栗子:
class Dog:# 这个是类属性,这样每个实例化对象都叫二哈了name = '二哈' # __init__是一个只要实例化一个对象就会被调用的函数,意思是,只要有dog1 = Dog()这个动作,就会被调用,该方法另出一章再讲def __init__(self):# 这个是对象属性,就是多了一个self.self.color = 'red' # 一条妖艳的红色狗狗# 定义狗叫的方法def barking(self):print('正在狗叫....')>>> dog1 = Dog()>>> dog1.name'二哈'>>> dog1.color'red'# 类调用对象属性需要这样写:类名().属性1>>> Dog().color'red'# 类直接调用对象属性是不行的。>>> Dog.colorTraceback (most recent call last):File "<pyshell#30>", line 1, in <module>Dog.colorAttributeError: type object 'Dog' has no attribute 'color'
(四)self是什么?
细心的读者会发现对象的方法里面都会有一个self,那么self是什么来的呢?
先语言解释一下,通过上面已经知道,一个类可以创造出无数的对象,那么一个对象要调用自己的方法那需要通过什么办法才能找到自己的方法呢,就是通过self。
先感受一下self
class Dog:def setName(self,name):self.name = namedef barking(self):print("狗狗{}正在叫!!".format(self.name))>>> dog1 = Dog()>>> dog1.setName('旺财')>>> dog2 = Dog()>>> dog2.setName('二哈')>>> dog1.barking>>>> dog1.barking()狗狗旺财正在叫!!>>> dog2.barking()狗狗二哈正在叫!!
拿小甲鱼🐢的栗子来说,如果把类比作房子的设计图纸,由类实例化后的对象才是真正可以住的房子。根据一张图纸可以设计出成千上万的房子,他们长得都差不多,但是它们的主人都不一样,所以self这里的作用就是相当于房子的门牌号了,有了self,才能轻松找到房子。
其实self这个单词不是固定的,你也可换成什么aaa,bbb这样的,但是代表的含义是一样的,但是我觉得我应该要保持良好的习惯😉,才能更开源,更容易理解。
class Dog:def setName(aaa,bbb):aaa.name = bbbdef barking(aaa):print("狗狗%s正在叫..." % aaa.name)>>> dog3 = Dog()>>> dog3.setName('旺财')>>> dog3.barking()狗狗旺财正在叫...
三、面向对象编程的三大特性
(一)封装
1、封装含义:
封装(encapsulation)即信息隐蔽。它是指在确定系统的某一部分内容时,应考虑到其它部分的信息及联系都在这一部分的内部进行,外部各部分之间的信息联系应尽可能的少。
大白话就是,某些确定功能的模块,比如扫拖机器人的扫地和拖地,是可以放在一起的,没必要弄一个扫地机器人,再弄一个拖地机器人,直接封装成一个扫拖机器人就可以。
需求:小明爱跑步
1.小明体重75.0公斤
2.每次跑步会减肥0.5公斤
3.每次吃东西体重会增加1公斤
代码封装:
class Person:def __init__(self,name,weight):self.name = nameself.weight = weightdef run(self):print('%s 正在跑步。。。' % self.name)self.weight -= 0.5def eat(self):print('%s 正在吃东西。。。' % self.name)self.weight += 1def __repr__(self):return '我的名字是%s,我现在的体重是%.2f' % (self.name,self.weight)>>> p = Person('小明',75)>>> p # 这个就是特殊方法(魔法方法)__repr__的作用。我的名字是小明,我现在的体重是75.00>>> p.run()小明 正在跑步。。。>>> p.run()小明 正在跑步。。。>>> p我的名字是小明,我现在的体重是74.00>>> p.eat()小明 正在吃东西。。。>>> p我的名字是小明,我现在的体重是75.00
2、封装公有和私有
在python中,默认的对象的属性和方法是公开的,只需要通过点操作符(.)即可进行访问:
class Dog:name = '二哈'>>> dog1 = Dog()>>> dog1.name'二哈'
有公开当然就有公开啦。就是在属性或则方法前面添加双下划线“__”。
直接调用会出错👇
class Dog:__name = '二哈'>>> dog1 = Dog()>>> dog1.nameTraceback (most recent call last):File "<pyshell#72>", line 1, in <module>dog1.nameAttributeError: 'Dog' object has no attribute 'name'
这样的意思是将类的变量名隐藏起来了,理论上只能从内部访问。
class Dog:def __init__(self,name):self.__name = '二哈'def getName(self):return self.name>>> dog1 = Dog()>>> dog1.getName()'二哈'
(二)继承
继承的含义:
继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。被继承的类称为“基类”、“父类”或“超类”。
要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。这个换一章再讲。
事实就是:继承的出现是为了偷懒,这是大实话。同类的事物的共同属性和方法不需要去重复定义,比如,鱼类,都有鳃呼吸的功能,都有吃的功能,不用每定义一条鱼都要重写这两个功能,直接继承鱼类这个父类的方法接即可。🌰举个栗子
# 定义一个鱼类class Fish:# 哈哈哈鱼鳃功能def breathInWater(self):print('我在水里呼吸!')def eat(self):print('我在吃海草!')# 定义一个草鱼,然后继承鱼类的吃和水利呼吸功能class GrassCarp(Fish):pass>>> gc = GrassCarp()>>> gc.eat()我在吃海草!>>> gc.breathInWater()我在水里呼吸!
这里再重点讲解一下,上面Fish类对于GrassCarp类来说是基类或者叫“父类”,GrassCarp类就是子类,需要注意的点是:
当子类的属性或者方法和父类的方法和属性重名时,子类的属性和方法会覆盖父类;
class Fish:# 哈哈哈鱼鳃功能def breathInWater(self):print('我在水里呼吸!')def eat(self):print('我在吃海草!')# 定义一个草鱼,然后继承鱼类的吃和水利呼吸功能class GrassCarp(Fish):def eat(self):print('我不吃海草,我吃肉的!!!')>>> gc = GrassCarp()>>> gc.eat()我不吃海草,我吃肉的!!!
想要了解多一点继承问题,可以去搜索一下 **“钻石继承问题”。**加深学习。 🙋♂
(三)多态
多态的含义:
以封装和继承为前提,不同的子类对象调用相同的方法,产生不同的执行结果。
事实就是:明明调用的是同一个方法或者属性,但是反馈的结果确是不一样的。😣
🌰举个栗子
class Dog:def eat(self):print('狗狗在啃骨头!')class Fish:def eat(self):print('鱼鱼在吃水草!')class Cat:def eat(self):print('猫在吃猫粮!')# 定义一个调用吃的方法:def function(cls):return cls.eat()>>> function(Dog())狗狗在啃骨头!>>> function(Fish())鱼鱼在吃水草!>>> function(Cat())猫在吃猫粮!
OVER~