python black horse编外学员
从今天开始我将逐一更新我在黑马python ai大开发学习的知识。
26/1/18
从今天开始我将逐一更新我在黑马python ai大开发学习的知识
Day1
面向对象
面向对象的概念
面向对象是什么,在理解面向对象之前我们应该先了解编程分有几类,主流的一共有两类,一类是面向过程比如传统的c语言,一类是python,java等的面向对象的语言。早期我们更多的是使用c语言,但是逐渐向着python,Java方向过渡,原因就是面向对象编程更能适配现代软件 “复杂、大型、需要长期维护和频繁迭代” 的核心需求(这个可能对于初学者很难理解,慢慢往后看)。官方的定义就是一种以对象为基本程序单元的编程范式,对象将数据(属性 / 成员变量) 和操作数据的行为(方法 / 成员函数) 封装为一个整体;同时通过继承实现代码复用,通过多态实现接口的灵活适配,最终达到提高代码可维护性、可扩展性和复用性的目标。对于初学者来讲很难理解是吧,通俗来讲就是面向过程是一步一步走的,而面向对象是以对象为核心,围绕此来解决软件设计问题的思想。它的核心思路是模拟现实世界的事物及事物之间的关系,让程序设计更贴合人类的自然思维方式。

面向过程

面向对象
这两个图很好的诠释了面向过程和面向对象的关系,面向过程更强调的是我在这个过程中到底做了什么,比如上图我执行一个c语言首先执行main主程序入口,接着执行main中相应的函数,最后输出结果。而python类的面向对象的编程语言更加强调的是我有一个而 Python 这类支持类的面向对象的编程语言,更加强调的是我有一个什么东西—— 我有一个具备特定属性和功能的对象,这个对象天生就带着描述自身的特征,还能独立完成对应的操作,不用再刻意拆解线性步骤,而是先定义 “东西” 的模板(类),再创建具体的 “东西”(对象),最后让这个 “东西” 自己完成要做的事。比如要实现 “查询一个用户的基本信息”,不会先想 “第一步定义变量、第二步写查询函数、第三步调用输出”,而是先想 “我有一个用户对象,这个对象应该有姓名、手机号、注册时间这些属性,还应该有一个‘展示个人信息’的方法”。先通过类来规定用户对象的 “标配”,再创建具体的用户实例,直接让这个实例调用自身的方法,就能完成信息查询和输出,全程聚焦于 “用户这个对象” 本身,而非繁琐的执行步骤。
看懂了吧,要是还没懂,你就想你在大街上看到一个漂亮的女生你要去搭讪,面向过程是我第一步要跟她打招呼,第二步要跟她要联系方式,第三步要跟她简单聊兴趣爱好,第四步尝试约她出来喝咖啡,每一步都要自己把控流程、衔接节奏,万一哪一步出错(比如忘了要联系方式就直接约咖啡),你就要重新开始了,后续想加个 “送她小礼物” 的步骤,还得在原有步骤里插进去,重新梳理整个搭讪流程。而面向对象是指已经在 QQ 上存好了她的方方面面的个人信息 —— 她的姓名、星座、喜欢的奶茶口味、周末爱去的公园,这些都是这个 “女生” 对象的属性;同时她还能和你聊天、跟你分享日常、答应你的约会邀请,这些都是这个 “女生” 对象的方法。你完全不用操心 “先做什么、再做什么” 的步骤,全程只需要聚焦于 “这个女生对象” 本身:想知道她喜欢什么,直接查看她的 “口味偏好” 属性就行;想约她周末出门,直接调用她的 “接受约会” 方法即可;后续想新增 “知道她的爱豆是谁”,只需要给这个对象补充一个 “偶像” 属性,不会影响她已有的姓名、联系方式这些信息;想加一个 “和她一起去看演唱会” 的操作,也只需给她新增一个 “陪同看演唱会” 的方法,不用推翻之前的所有准备,这就是面向对象的核心优势 —— 聚焦对象本身,属性和行为自带,扩展和调整都不影响全局。
类和对象
好了理解了这俩的区别之后,接着我们来谈面向对象这个东西到底是个什么玩惹。面向对象下层有两个核心的知识,一个就是类,一个就是对象。类的意思就是对一群具有相同特征或者行为的事物的一个统称,是抽象的,不能直接使用,比如说狗类。特征被称为属性,行为被称为方法,类 就相当于制造飞机时的图纸,是一个 模板,是 负责创建对象的。

对象 是 由类创建出来的一个具体存在,可以直接使用,比如说人是类,对象是具体的某个人,在程序开发中,应该 先有类,再有对象。


上面两张图就是谈它们的区别。
类的开发和设计
在使用面向对象开发前,应该首先分析需求,确定一下,程序中包含哪个类。在开发程序的过程中通常需要包括三要素:
类名:这类事务的名字,满足大驼峰命名法
属性:这类事务有什么特征(也就是名字之类)
方法:这类事务有什么样的行为(通常为动词)
大驼峰命名法
CapWords
即每个字母大写,不需要_下划线连接
例子:小帅今年 21岁,身高 1.75,每天吃八个馒头,晚上会去打篮球
这里的小帅就是对象,而他属于人这个类,人这个类有名字,身高属性,方法就是刚刚提到的吃,打动作。
Day2
面相对象基础语法
第一个大类:
Python给我们提供的内置方法常用的有如下四种:

第二个大类:
就是自定义方法,语法格式如下

注意:如果我们定义一个类且类里面包括了python自带的内置方法,我们不需要在声明启用内置函数,python会自动的启用内置函数。
上面表述的可能过于抽象下面举一个例子来感受感受
小猫爱吃鱼,小猫爱喝水
分析:
类是谁猫
对象是谁小猫(别忘了对象是类的实例)
属性无
方法(动词):吃,喝
类定义如下示例:

这里强调Cat是一个独立的单元,tom是指向cat的一个引用,在python使用类创建对象之后,tom变量中仍然记录的是对象在内存中的地址。也就是tom变量引用了新建的猫对象。在使用了print输出cat时,它会输出所属于哪个类和它的16进制地址。
顺便提一嘴就是在python的视角里万物皆可面向对象,例如变量(int)、数据、函数 都是对象
比如说数据1在python中被归为int类,int的父类是object,所以int继承了所有的object的方法例如__str__你可以直接print(1)得出的结果是1,还可以__eq__判断是否相等,函数是function的实例,它可以继承__name__等方法。
解释以下上图的self是啥就是tom,要是你不理解的话你拿pycharm跑一下 在tom.cat()那里设置一个断点看看self,或者你在eat()函数那里输出以下self的地址和tom的地址是否一致也能证明。
Day3
常见的python内置函数
01. __init__(self)
在python中我们可以在类的外面给对象设置属性,例如:

但是有问题就比如说我们开发的时候就不好维护缺少扩展性,通俗来讲就是很难修改,要一个一个排查很麻烦,而且在很多个对象都拥有的属性时我们需要很多行来定义很繁琐,所以我们用python内置的方法__init__(self):如下图:

所以以后我们在给类做属性设置时在__init__()里面就行了,不用在类外面再设置属性
02. 内置方法和属性
2.1
过程如下代码:

2.2
__str__方法
在python中,使用print输出对象变量,,默认情况下,会输出这个变量引用的对象是由哪一个类创立的对象,以及在内存中的地址。如果开发中,希望用到print打印自定义内容,就要修改__str__方法,把它的返回值修改成你想要让他成为的样子。

Day4
面向对象封装案例
封装是面向对象编程的一大特点,面向对象我们往往需要把属性和方法封装到一个抽象的类中。这样我们在调用类对象时不需要考虑它的具体实现细节,只用考虑类对象,围绕着类对象的属性和方法展开做事。下面举两个例子来具体感受一下。
1.小明爱跑步
需求如下:
小明的体重是75kg
小明每次跑步会少0.5kg
小明每次吃东西会增加1kg
分析:
谁是类:人
谁是对象:小明
谁是属性:名字,体重
谁是方法:跑步和吃东西
接着我们来写类:代码如下

代码解释__init__()表示的是python内置方法,不管你在类外部是否注明有无此方法都自动执行,里面放着类的属性值,__str__是调用print函数输出的值,默认设置为对象输出属于哪一个类和16进制地址,run(),eat()方法就是表示自定义的跑和吃的方法。Xiaoming=Person(“小明”,75)里面的参数Xiaoming=self,”小明”=name,75=weight。
扩展提示:在对象方法内部是可以直接访问对象的属性值的,比如说:


上图的weight属性值就被吃东西引用了。
第二个扩展知识点就是同一个类 创建的 多个对象 之间,属性互不干扰。比如说:
Xiaomei=Person(“小美”,45)
她和小明是不一样的,你输出xiaomei的地址或者xiaomei.name的出来的结果都是不一样的
2.摆放家具
需求:房子有户型,总面积和家具列表名称,同时新房子里面没有任何的家具,新添进来的家具有名字和占地面积,其中

- 将以上三件家具放到房子中,打印房子时,要求输出:户型、总面积、剩余面积、家具名称列表
分析:
类:house
对象:什么样房子
属性:家具列表,总面积,户型。
方法:添加家具
我用两种方法来展示:
第一种:


第二种:


代码讲解首先第一个定义房子类,我们要定义房子属性

其次我们要定义家具相关属性

第二步方法:

先判断此家具是否大于总的占地面积,如果大于则返回,不大于就添加在列表中,随即用总的面积去减去家具所占的面积
在这个案例里,用两个类(House类和Furniture类)比只用一个House类要更简单好懂、还好维护。如果只写一个House类,就得在里面既记房子的户型、总面积,又记家具的名字、面积,还得用两个列表分别存家具名和面积,一不小心就会记混顺序,这里有一个小技巧什么时候使用一个类,什么时候使用两个类,先看要写的内容能不能拆成两种不同的东西,房子有户型,总面积,家具有名称和占地面积,那就写两个类,要是都是讲人的身高体重年龄就写一个类,多练练才好辨别,绝知此事要躬行。
还有一个要提的地方就是remaining_area这个是专属于my_house这个实例的,你塞家具进去会对占地面积是由影响的。
小结以下就是,主程序只负责创建房子对象和家具对象,让房子对象调用add_furniture来添加家具。面积计算和剩余面积,家具列表等处理都被封装到房子类的内部。
Day5
3.士兵突击
今天我们以士兵突击来举例子。
士兵突击里面有个队员叫许三多,他有一把枪叫ak47,士兵可以开火,枪可以发射子弹,枪也可以上子弹。
在分析这道题之前我们要知道就是被调用对象应该先创建于调用对象之前,所以有题我们可以分析出这里面之中包含两个类,一个是枪类,一个是士兵类。枪类应该写在前面。
枪类
类:枪
对象:ak47
属性:名称
方法,可以发射子弹,可以上子弹,但是不可以开火,因为开火是士兵要做的事情。代码如下。
代码分析,首先定义属性,枪的model是什么也就是名字ak47,子弹的数量初始值设置为0,add_bullet函数执行后会修改bullet_count的值,最后是射击判断枪里面是否还有子弹,发射一颗子弹则减一颗。
士兵类
假设每一个士兵都开局都没有分配枪,如果我们什么值都不知道就设置为None。
分析士兵类:
类:士兵
对象:xusanduo
属性:名字,枪
方法:射击,分配枪支
小提示一下:就是要看清楚做的主语是谁,代码展示如下:

代码解释我们可以使用xusanduo.gun=ak47来分配枪支,并继承ak47类也可以在类内部定义一个获得枪支的方法,:fire函数中我们先判断许三多是否被分配枪支。
day6
身份运算符
我们要区分is和==的区别

例如:在python中输入a1=[1,2,3],a2=[1,2,3]
a1 is a2 得出来的结果是false 因为is是用来看它们俩的地址是不是一样的
a1==a2 的出来的结果是True 因为==用来表示的是它们两个的值是否一致
私有属性和私有方法
1.应用场景和方法
在实际开发中,对象的某些属性和方法可能只希望在对象的内部被使用,而不希望在外部被访问到
Python中的私有性如何表示,在定义属性和方法时,在前面增加两条下划线,这就是私有属性或方法

如上图代码中__age在控制台中无法显示,__secret也无法显示
2.如何访问私有属性和方法
在python中并没有真正意义上的私有,而是在给属性或者方法命名时,实际上是对名称做了一些特殊处理,使得外界无法访问,处理方式就是在名称前面加上_类名__名称,例如下图所示。

Day7
继承
面向对象三大特性
- 封装,根据属性和方法封装到一个抽象的类中
- 继承 实现代码的重复使用,相同的代码不需要重复的编写
- 多态 不同对象调用相同的方法,产生不同的执行效果,增加代码的灵活度
1.单继承

图1
如图所示xiaotianquan是dag类的子类,animal是dag类的父类,dog类可以继承animal类的所有属性和方法,意思就是

图1

图2

图3
图1中定义一个动物类有吃和睡的方法,图2中只在狗类中有狗叫这个方法,在控制台中创立狗对象,直接把旺财,金毛传入进去,python解释器没有报错,原因是dog类对象继承了animal得属性值和方法。
提示:因为有些同学学到一定知识后会达到一个混淆就是父类.方法(self)和super().父类方法()是不是一样的,在大部分情况下这确实是一样的,比如说单继承,但是单从代码维护和扩展方法不行,假设你要修改Animal()父类名字变成BaseAnimal()那你所相关的其他都需要改变,这不利于我们说的python是一门面向对象的编程语言。不能很好的分成一块一块的。总结如下,下面是一个理解联想。

2.多继承
子类可以拥有多个父类,并且拥有多个父类的属性和方法,如下图1所示

注意事项:在开发多继承时,应该避免父类重名,否则会导致在开发过程中不知道调用的时哪一个父类。
Python中可以用__mro__可以来查看调用的顺序例如:class c(a,b),调用顺序为c,a,b.
方法的重写
1.覆盖父类的方法(全覆盖)
在上一小节我们介绍了继承这个概念,接着我们来谈在开发时,我们在继承父类的属性和方法时,如果我们对于父类的方法我们想进行修改,但是不想影响别的通过此父类创建出来的对象,我们就可以通过方法重写来做到。

图1
![]()
图2
代码如上图1,解释一下就是父类animal调用eat()得出来的结果是旺财吃普通食物,但是控制台输出的结果是,旺财吃骨头,这是为什么呢,原因是,我在dog类中又重新写了一个eat()的方法,这导致在dog.eat()方法调用时,不需要向上寻找它的父类,自己就可以控制台输出,这我们也可以得到一个结论,就是自己的优先级是大于父亲的,大于爷爷的。
2.对父类进行扩展
这个是啥意思呢,就是你父亲做了一个宏图霸业,而你所做的就是在他的基础上,把一些边边角角给他补全。
需要的方法就是super().父类的方法来调用父类方法的执行.

图1

图2
执行上述图1代码会获得图2的结果,这是为什么呢。因为在dog.run中代码super.run()继承了animal的run()的代码。导致了会有旺财在奔跑的结果,与此同时继续执行还得到了旺财奔跑时会摇尾巴,还会汪汪叫的结果。不同于上一小节讲的不会执行父类的代码,上一小节讲的时全覆盖,这里时保留了父类,并没有全覆盖。
3父类的私有性和私有方法
上上一讲,我们讲过私有化是指只能在本类中访问,而到外面类中是无法访问的,本次我们来讲一下在子类继承中如果我们调用父类的私有属性和私有方法时是否能正常访问。

图1

图2

图3
图1中定义两个方法一个私有方法__sleep()一个公有方法eat(),图3中我们试图在dog类中访问父类animal的私有属性和私有方法,结果失败,这是因为我们在本开头讲的私有化是指只能在本类中访问。
如何在子类中访问父类的私有方法和私有对象呢?

图1

图2

图3

图4
解释代码animal有一个私有属性值为name,私有方法__name(),__sleep(),公有方法,公有get_name(),do_sleep(),do_eat(),dog类中的show方法展现出获取父类得
get_name(),do_sleep(),do_eat()得信息,最终结果如图4所示。
Day8
单例
什么是单例
今天为什么要讲单例这个事情呢?就是我们创立实例对象需要耗费许多的资源,比如说你创立一个实例对象a你就需要占一个地址给他,除非启动free()函数销毁否则,对象一直存在知道程序结束。要是我们需要做的工作是重复的,谁来都是那一套,我们就可以使用单例,简单来说单例就是只开辟一个实例对象的地址,其他的实例对象都是映射在这个地址上的,所以你创立实例对象a和b,以a作为基准,修改b则a的属性和方法也会被修改。
单例的使用场景

如何实现单例
__new__方法:
在介绍单例模式的实现前,我们首先要理解__new__方法的作用及 Python 创建对象的底层逻辑:当使用类名()创建对象时,Python 解释器会先尝试调用该类自身的__new__()方法,若该类未重写此方法,则自动调用其父类(所有自定义类默认继承的根父类object)的__new__()方法,object.__new__的核心职责是为实例对象分配唯一且由系统规则分配的内存地址(而非给类随机分配地址),并返回该地址,待内存分配完成后,解释器才会调用类的__init__()方法初始化对象属性;而实现单例模式的核心思路,就是重写自定义类的__new__方法(子类重写的方法会覆盖父类的同名方法),在重写的__new__中添加判断逻辑,仅在第一次创建实例时主动调用父类object的__new__完成内存分配,后续创建实例时直接返回第一次分配的内存地址,以此保证该类在程序运行过程中始终只有一个实例。

图1

图2
代码解释:
场景一即为图1这个就是原本object里面的代码,就是你调用一次__new__就给你分配一个地址。场景二即为图2,这是我们自定义的__new__代码。首先我们定义一个instance=None,其次我们重写__new__()方法,我们举个例子如何运行这串代码。首先我们先定义两个实例对象a,b。Musicplayer是他们的类,启动程序首先,python解释器会先去启动__new__方法,寻找地址,因为首次访问地址值为none,所以会向上寻找父类执行cls.super().__new__(cls)代码,之前说过super().父类方法()就是调用父类的方法。接着我们创立b这个对象,此时instance已经有值且等于a的instance值所以不需要创立新的地址,直接启用a的地址就行。这个不理解的同学可以用我的代码示例回去练一练。
Day9
异常
今天我们来讲开发中我们常遇到的问题就是异常。如果python解释器遇到异常就会停止程序的执行,并且提示一些错误的信息,这就是异常。在程序开发时我们很难将所有问题想的面面俱到,通过异常捕捉可以针对突发事情做集中处理
1.简单的捕捉异常的语法
在程序开发中,如果对某些语法执行不能确定是否会报错,可以尝试使用try来捕获异常,捕获异常最简单的格式如下:

图1
我们将我们想尝试的代码写入try当中,如果try代码执行不成功转而执行except的代码,然后继续执行之后的代码。不会出现程序突然暂停的事情。
2.捕获类型异常

图2
代码解释和try里面写的代码同上,except里面写着错误类型。类似于c语言中的switch/case一样。最后的except exception as result是指我们不能面面俱到的发现所有的错误情况,所以当上述except 错误类型没有提到时就会跳转到此来执行
3.异常捕捉完整语法

图3
这是异常捕捉的完整语法情况,上面标有具体的代码解析,笔友就步详细解释了。值得注意的是这时候对比于上面两个代码差别是多加了一个else和fally的情况,else里面如果try里面的代码执行成功的话就会执行else里面的代码,无论执行成不成功都会执行finally的代码,然后继续往下执行。
已经更新完面向对象的所有语法情况和有关介绍情况有什么问题或者笔友有什么写的不对的地方欢迎私信笔友,接受大家的批评和指正。
更多推荐



所有评论(0)