Python——面向对象开发基础

P1 面向对象的概念
面向过程编程,在编写函数时,会出现你调用我,我调用你的情况,函数的参数也会出现不同和变化,在这种复杂情况下,使用面向过程编程,比较繁琐
而面对对象编程,首先要明确不同对象和它们的职责,很少出现互相调用函数的情况,明确了各自的功能,再编写函数,调用自己的方法,简化了复杂项目的开发工作。

P2、类和对象 

类就是制造飞机的图纸,不能直接使用,但是有属性和方法

对象是这个图纸造出来的飞机,可以直接使用的,同时拥有了这类飞机的属性和方法

 一个类可以有很多个对象,不同对象之间的属性可能不同

但是同属一个类的对象,它们之间的属性和方法不能多也不能少

P3 如何设计类?(很重要)

步骤: 需求分析>创建类名、属性、方法>大驼峰命名法

P4 dir 查看内置函数和方法

在Python中对象是无处不在的,之前学习的变量、数据、函数都是对象

P5 定义一个只包含方法的类

面向对象就是更大的封装

1、方法的参数中至少要有一个self参数

2、类的命名要符合大驼峰命名法

如何创建对象?

P6 

将方法封装在类中,在调用时不关心实现的细节

类名加上小括号就可以创建一个对象,当对象创建完成,就可以用 “点”的方式调用类中封装的方法

 注意:创建对象之后,变量中仍然记录的是对象在内存中的地址

P8 创建多个猫对象

 

 类只有一个,使用相同的类可以创建多个不同的对象

P9 在类的外部给对象增加属性(但是不推荐使用)

在类的外部如何添加?对象名 . 属性名 = 属性内容   

对象的属性应该封装在类的内部

P10 利用self参数在类封装的方法输出对象的属性

哪一个对象调用的方法,self就是那个对象的引用。

tom调用时,self就指向tom; lazy_tom调用时,self就指向lazy_tom

在方法内部想要访问属性,就可以使用“self . 一个属性”即可

可以用调试中单步执行的方法验证,当进入类中的方法时,self指向的是调用对象的地址

 在调用方法的时候不用传递self参数,但是在创建方法的时候第一个参数必须是self参数

P11 类的外部给对象增加属性带来的问题——可能找不到属性

P12 初始化方法

只是去创建了一个新的对象,我们没有调用__init__方法,但是它仍会执行。 

 __init__是所有对象的内置方法,在使用类名()创建新的对象时,就会自动执行,所以我们可以使用这个初始化方法去为对象的属性设置初始值

P13  在初始化方法内部定义属性

保证以后创建新的对象时,都会有这些属性

P14 利用形参设置属性初始值

当不希望把方法中的变量写死时,就要用到形参

 

P15 del方法 和 对象的生命周期

当一个对象创建时,分配完内存空间后,会自动调用__init__方法

当一个对象被从内存销毁前,会自动调用__del__方法

所以可以改造这两个方法,找到这两个方法的应用场景

P16 __str__方法

 改造__str__方法时,必须返回一个字符串

__str__方法的使用场景:改变 对象变量 默认打印出来的情况

P17 面对对象封装案例

在对象的方法内部,是可以直接访问对象的属性的 

P19 多个对象之间的属性互不影响

P20 摆放家居

遇到问题,需求分析很重要 

多个类中,被使用的类先开发

P24 一个对象的属性 可以由 另一个类创建的对象 构建

一个对象(士兵)的属性(枪)可以是另外一个类(枪)的对象(ak47),通过赋值语句赋值即可

这个对象的 属性变量    会指向    那个对象的内存空间

P25 

在开发时,想要定义一个类的属性,但是又不知道给这个属性赋什么值时,可以设为None,

  

P28  判断是否None应该使用 is 身份运算符(根据PEP8的编码规范要求的,使用==也可以,但是不规范)

 is 是用于判断两个变量的内存地址是否相等

==是用于判断内存地址中的值是否相等

P29 私有属性和私有方法(在属性或者方法前加两个下划线定义)

它的应用场景:对象的属性和方法只希望在对象的内部被使用,不希望在对象外部被访问到

P30 伪私有属性和方法

在Python中是没有真正意义上的私有,改写后,私有属性和方法都可以被访问

 知道了Python对于私有属性和方法的处理方法,按照处理方法,就可以访问这些私有属性和方法了

使用"_类名__私有属性"或者"_类名__私有方法"就可以访问这些私有属性和方法了

继承(这里只讨论逻辑上的关系,物理上的实现方式不深究)

P31 问题的提出:单纯的封装可能出现重复的代码

 

继承实现了代码的重用,相同的代码不需要重复的编写

实际应用中:狗类具有动物类的特性,在编写狗类的时候,不使用继承,那我们就要复制动物类特性的代码,放在狗类代码中,我们不想使用这样的方法,同样的,当动物类的代码改变时,我们也要重现复制粘贴,再一次改变狗类的代码

>>“继承”的概念应运而生

P32 继承的语法和特点(在“子类名” 后加上 “父类名”就可以继承了)

 

继承:子类拥有父类的所有方法和属性

子类可以直接享受父类已经封装哈的方法和属性,不需要再次开发

两种术语的表达:

P34 继承的传递性

子类拥有父类的方法和属性,同时也拥有父类的 父类的(爷爷类)的方法和属性

P35 继承传递性的注意事项:只能向上继承父类的属性和方法

P36 方法的重写

使用场景:父类方法的实现,不能满足子类继承下来的这个方法的需求,就需要重写方法

如果子类中,重写了父类的方法,在使用子类对象调用方法时,会调用子类中重写的方法,而不会调用父类中的方法

具体的实现方法:在子类中定义一个和父类同名的方法并且实现

P37 方法重写的拓展

在父类方法的实现 满足不了子类实现的需求时,就需要重写父类的方法

>>>但是出现了我们同时想在重写的方法中调用父类的某些方法,就可以使用“super().方法名”调用父类的任意一个方法(这只是一种情况)

>>>>>>任何子类的方法中想要调用父类的方法,都可以使用 super().方法名 调用父类的方法

 

P39  子类对象中不能直接访问父类的私有属性和方法

1、子类对象不能在外部直接访问父类的私有属性和私有方法

2、并且子类对象不能在自己的方法内部,直接访问父类的私有属性和私有方法

>>子类对象不能直接访问父类的私有属性和私有方法

!!!这里虽然说的是不可访问父类的私有属性和方法,其实本质是子类自己没有继承下来这些私有属性和方法的意思。

关键:子类继承了父类的所有公有的属性和方法,但是私有的不继承,同时父类的那些私有的属性和方法,子类也不能访问和调用(这里只涉及到一个  子类的对象)(讨论的是如何访问父类的隐私的问题)

子类对象可以借助于父类的公有方法,访问父类的私有属性和私有方法

同时或者在子类的方法内部借助父类的公有方法

子类对象访问父类的公有方法天经地义、父类的公有方法访问自己的私有数据和私有方法也是天经地义>>>通过这两步,子类对象可以 借助于父类的公有方法,访问父类的私有属性和私有方法

P41 多继承

 多继承可以让子类对象,同时拥有多个父类的属性和方法

P42 多继承的注意事项

例如:class C(A, B)    C类创建的对象调用方法,当A,B有方法重名时,优先调用括号左边A类中的方法(先入为主)

P43 类的内置属性:__mro__属性(方法搜索顺序)

使用场景:在多继承中,要查看这个类中某个方法的搜索顺序的

可以使用print(类名.__mro__),会告诉你这个类中所有方法,是按照什么样的 类 的顺序执行的

即执行方法时,左边的类找不到这个方法时,会依次向右查找,第一次找到了就执行这个类中的方法

P44 新式类和旧式类

object类是Python3.x中所有类的基类,所以新建的类会默认有一些内置的方法和属性(都是从object继承下来的)

可以使用 dir(对象名) 查看

P45 多态:以继承和重写父类为前提

封装>>>继承>>>多态,三者是循序渐进的,递进的关系

继承以封装为基础,多态以继承为基础

P46 多态案例

P47 创建对象的过程、实例的概念

使用类名创建对象的过程:1、在内存中为对象分配内存空间 2、调用初始化方法__init__

重点:

1、不同对象  :各自的属性在各自的内存空间

2、对象的方法在内存中是如何保存的呢?

所有对象的方法在内存中只有一份。当一个对象调用这个对象的方法(代码其实是在类中)时,会将类中方法中的self参数指向这个对象实例

P48  类是一个特殊的对象

程序运行时,类同样会被加载到内存中

类对象在内存中只有一份,使用一个类,可以创建出很多的对象(每个对象的内存空间中保存着自己的属性,但是对象的实例方法是保存在类的内存空间中的)

上图区分:类属性、类方法、实例属性、实例方法

当对象调用方法时,是将对象实例的引用  传递给类中的self

对象的实例方法是保存在类的内存空间的

类对象也有自己的属性和方法

类属性、类方法是针对类而言的。实例属性、实例方法是针对对象而言的。它们有不同的内存地址

P49 类属性的定义和使用

 类属性 类似于 全局变量,是属于这个类的,通过“类名 类属性名”访问

使用场景:使用类属性用来记录与这个类相关的特征,专门记录与类这个模板相关的特征,不用来记录与具体对象有关的特征        

P50 类属性的查找机制

使用 “对象 . 类属性” 访问 类属性 时,先在对象属性内部找这个属性有没有,没找到再找类属性。

访问类属性:不建议使用“对象 . 类属性”,读取时没有问题,但是一旦使用了赋值语句,会给这个对象多添加一个属性

P51 使用“对象名+类属性”的赋值语句会创建对象实例的属性 

第19行:使用“对象名+类属性”的赋值语句会创建对象实例的属性 

核心:类属性的内存空间、各个对象实例的内存空间都是不同的

P52 类方法:针对类定义的方法

语法有两点注意:1、上面的修饰符 2、第一个参数是cls

P53 类方法的案例演练

P54 静态方法:既不访问类属性,也不访问实例属性的方法

静态方法的应用场景和定义方式:

 调用“静态方法”和“类方法”都是通过 “类名.” 的形式调用

P55 综合案例分析

1、首先进行需求分析>>>设计类>>>分清类属性(和某个具体的对象无关的属性)和实例属性 

2、需要访问“类属性”的方法设为“类方法”,需要访问“实例属性”的方法设为“实例方法(就是对象方法)”,既不访问“类属性”也不访问“实例属性”的方法设为“静态方法”

P58 单例设计模式

单例设计模式解决的问题就是:不论我们执行多少次的 “类名()” 创建对象,它们的内存地址都是相同的,即在系统中只有一个唯一的实例 (创建出来的对象在内存中只有唯一的一个实例)

P59 __new__方法

1、先了解下__new__方法

__new__方法是由object基类提供的内置静态方法,使用 “类名()” 创建对象时有两个主要作用:一,在内存为对象分配内存空间;二,返回这片内存空间的引用 给Python解释器,然后Python解释器会将这个对象的引用作为__init__初始化方法的参数传递给self ,self形参就指向了对象实例,由初始化方法对传递进来的对象进行初始化操作

2、为什么学习__new__方法?

就是因为我们要对分配空间的方法进行改造,改造的目的就是当我们使用“类名()”创建对象的时候,无论执行多少次,在内存中只会创建出一个对象的实例,这样就可以达到单例设计的目的

 __new__方法只负责分配内存空间,不负责返回内存空间的引用给解释器,必须要return super().__new__(cls)

P60 单例设计模式的实现

P63 初始化动作只执行一次

解决办法:

P64 异常的概念

P65 捕获异常

在程序开发中,对于某些代码,不能确定是否按照正确的流程执行,例如让用户输入这部分,用户可能不会按照规范的方式去输入,则这部分就不能确定是否能正确的执行>>>可以增加try来捕获异常

注意:捕获异常中,不论是正确的执行,还是执行出现错误的处理,都会继续向下执行,不会因此停止下来 

P66 根据错误类型捕获不同的异常

格式:“except 错误类型:”   ---多写几个

P67 捕获未知错误---格式基本固定的

使用场景:无法预判错误的发生,且不想让程序因为Python解释器抛出异常而被终止时

 result 是一个接收异常的变量名,可以更改

P68 异常捕获的完整语法

注意:else和finally中的代码什么时候会执行(下方有两种执行流程)

P69 异常的传递性---只需要在主函数中增加异常捕获,被调用的函数中都不用增加

在程序执行时,如果某个函数出现了异常,会把这个异常向上传递,传递给函数的调用一方,一直传递到主程序之后,如果没有发现异常处理,程序才会被终止。

 

P70 抛出raise异常---根据应用程序特有的业务需求,主动抛出异常

P71 主动抛出异常 演练(重点)

Exception是一个异常类,我们要主动抛出一个异常,就要先创建一个异常对象,然后再用raise关键字抛出这个异常对象

可以主动创建不同的异常对象,来捕获这些不同的(我们自定义的)异常

P72 模块

1、每一个以“.py”拓展名结尾的文件就是一个模块

2、模块名也是标识符,也要遵守标识符的命名规则

3、模块中的全局变量、函数、类都可以作为外界使用的工具,而模块就是一个工具包

推荐使用第二种导入方式(符合PEP8的标准)

使用“模块名 .”的方式使用模块提供的工具

P73 给模块起别名

1、别名要符合大驼峰命名法(单词首字母大写、单词与单词之间不需要下划线)

2、别名 只是在当前文件下使用,模块的实际名称还是原有的

P74 from...import导入

 注意:

1、import导入是一次性导入模块中的所有工具,并且通过“模块 .”的方式使用函数、类或者访问全局变量的

2、from...import导入只导入部分工具,并且不需要通过模块 .”的方式使用函数、类或者访问全局变量的

P75 from...import导入同名工具的注意事项 --- 导入同名函数,后导入的会将前面导入的覆盖掉

如果就是想调用不同模块中两个同名的工具,可以采用给前面一个函数起别名的方式

P76 from...import导入全部(不推荐使用)

 优点:调入的工具包,在使用时,不用加前面的“模块名 .

P77 模块的搜索顺序

Python解释器导入模块时,先搜索当前目录,看是否有指定的模块(.py文件),如果有,就直接导入,如果没有,再搜索系统目录

 

1、一旦在当前目录下找到random模块,就不会去系统目录下去找了

2、使用  print(模块名.__file__) 可以查看这个模块的绝对路径

>>>模块名不要取和系统模块一样的名字

P78 开发原则---每个模块都可以导入>>>简单的导入会带来了一些问题

在一个模块中向外界提供的工具包括:全局变量、函数、类

能够直接执行的代码(例如print语句)不是向外界提供的工具

 我们想要每一个文件都是可以被导入的,但是在导入文件时,文件中所有没有任何缩进的代码都会被执行(即导入时,有些能够直接输出的代码,我们不需要它这时候执行)

P79 __name__属性兼顾测试和导入两种模式

在hm_09___name__模块中顶格写“print(__name__)”会直接输出__main__

但是在导入“hm_09___name__模块”的“hm_09___name__测试导入”模块中,会输出“hm_09___name__模块”这个模块名

总结(原理):

1>>>__name__是Python的内置属性,不属于任何一个模块

2>>>执行当前A模块时,__name__等于__main__,但是在执行B模块中,(因为B模块导入了A模块,所以输出__name__的语句会被自动执行,但是它不等于__main__了),而是那个A模块中的__name__等于A模块名

 开发时,常用的套路,这样主程序用于测试时会被执行,文件被当做模块导入时,又不会执行主程序中的代码

P80 包的概念

新建包的两种方式:(包的名字必须以字母下划线开头)

1、右键>New>Directory>命名包的名字>再右键>新建一个以“__init__”命名的Python文件>完成

2、右键>New>Python Package>命名包的名字

P81 如何使用 包 中模块

1、先在__init__.py文件中指定对外界提供的模块

2、再导入包名

3、最后使用包中模块中的函数的格式:包名。模块名。工具名

P82-P85 制作发布压缩包 的 三步

P86 

P87 文件的类型

文本文件是可以用文本编辑软件查看的文件(但本质上还是二进制文件)

P88 文件的基本操作

操作文件的三个步骤(不论读写都是固定的)

open只是打开文件,并且返回文件的操作对象(即只是将文件的内存地址,放在内存中的文件目录中),文件中的具体内容并没有到内存中

P89 读取文件

文件名是区分大小写的

 

P90 

1、第一次open打开文件时,文件指针会指向文件的开始位置

2、当执行了read方法后,文件指针会移动到文件内容的末尾(默认情况下)

 

P91 文件的打开方式

open方法默认是以只读的方式打开的(文件指针(目录)调入内存),这时调用write方法是不可写的

需要添加控制信息打开文件

重点掌握 只读、只写 的方式

“w”以只写的方式打开,如果调用write方法写内容进入文件,则会将原本已经存在的文件内容覆盖掉

“a”(append)以追加方式打开,如果调用write方法写内容进入文件,则会将内容追加在文件末尾

P92 readline方法,分行读取内容

P93 复制文件

P94 Python中如何执行文件/目录的管理?

在Python解释器中导入os模块,也可以执行文件/目录的管理操作(和在Linux终端中操作文件/目录是一样的)

P96 文本文件的编码方式

 

 1个字节描述一个字符>>>1-6个字节描述一个字符(涵盖的字符更多了)

 P97 

在Python2.x的解释器中,执行带中文字符的文件时,使用utf-8的编码格式,是能够输出中文的

但是如果是要遍历某个带中文的字符串,是会输出???的,一个中文对应三个问号(一个汉字占三个字节,且ASCII编码是按一个字节编码的),因为解释器在遍历字符串时,仍然以字节为单位遍历字符串,如果要避免这种情况,遍历字符串时,在字符串前面要加 u

P99 eval函数

 

滥用eval会导致系统不安全!

  

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

#学习的路上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值