一、上堂回顾
1.默写题目
1.封装函数,输出一个路径下的所有的文件以及文件夹
import os def getAll(path): #1.判断路径是否存在 if os.path.exists(path): #2.将指定路径下的所有的文件以及文件夹获取出来 #注意 :返回的结果为列表,列表中的元素是文件以及文件夹的名称的字符串 fileList = os.listdir(path) #3.遍历列表 for fileName in fileList: #4.拼接路径 #注意:父路径 + 文件或者文件夹的名称 filePath = os.path.join(path,fileName) #5.判断二级目录下的路径是否是文件 """ if os.path.isdir(filePath): #目录 pass else: #文件 """ if os.path.isfile(filePath): #文件 pass else: #目录 pass else: print("不存在")2.自定义模块,其中定义函数,在另外一个py文件中调用
module.py
def test(): passimport module #调用函数 #注意:如果采用import的方式导入模块,调用函数的格式:包名.模块名.函数名() module.test()
2.知识点回顾
1.栈和队列
【面试题】:栈和队列的区别和联系
栈和队列的工作特点:
2.包
在Python中,package【包】
特点:管理模块【py文件】,避免模块命名冲突的情况
3.模块
系统模块
time:时间戳,元组格式,格式化字符串三种之间的相互转换
os:主要操作文件以及文件夹
二、自定义模块
1.import模块
代码演示:
module.py
def fun1(): print("hello~~~1111") def fun2(): print("hello~~~2222") def fun3(): print("hello~~~3333") def fun4(): print("hello~~~4444") fun1() fun2() num = 10textDemo01.py
#导入模块 #注意2:如果需要导入的模块有多个,使用一个import,不同的模块之间使用逗号隔开,自定义模块和系统模块可以同时使用 """ import module import module1 """ #格式:import module1,module2,.... import module,module1,os,math #注意3 :一个模块不管import几次,都只会被加载一次【单例设计模式】 #import module #调用函数 #module.fun1() #注意1:在不同的文件中,如果出现重名的函数,调用函数的时候,根据函数的相对路径区分调用的是哪个函数 def fun1(): print("text~~~") fun1() #module.fun1() module1.show() #模块的好处:可维护性高,可读性高
2.form -import 模块
代码演示:
def fun1(): print("hello~~~1111") def fun2(): print("hello~~~2222") def fun3(): print("hello~~~3333") def fun4(): print("hello~~~4444") fun1() fun2() num = 10textDemo02.py
#from...import #语法:from 包名.模块名 import 函数名1,函数名2.... #注意:表示 从xxx导入xxx #需求:只调用module模块中的fun1和fun2 from module import fun1,fun2,num #import module #调用 #module.fun1() fun1() #fun3() #总结:from...import表示从一个模块中导入一部分内容【只将指定模块中的部分函数加载到内存中】 #适用场景:如果一个模块中有很多功能,通过form...import可以只使用需要的功能 """ import和from...import之间的区别: 函数的调用: import:包名.模块名.函数名(实参列表) from。。。import :函数名(实参列表) """ #补充1:在模块中定义一个变量,也可以和函数一样使用【函数名就是一个变量名】 print(num) #10 #补充2:使用from。。。import的方式导入模块,如果当前文件中出现和模块中同名的函数的时候,优先调用的是当前文件中的函数【就近原则】 def fun1(): print("textdemo02~~~") fun1()
3.from-import*模块
4.name属性和dir函数
4.1name属性
__name__:指定的py文件作为模块使用的话,如果不想让模块中的某些代码执行,则可以使用__name__限制需要被访问的部分 注意:每个模块都有一个__name__属性,代表了模块的名字,当它的的值为__main__时,表明是该模块在运行,反之,则说明是引入的第三方的py文件在运行
5.安装第三方模块
在终端中执行命令:pip
pip install 第三方模块名称
三、面向对象
1.面向对象思想设计
1.1案例
万物皆对象
举例说明:
面向过程【面向处理】
案例一:我今天吃大盘鸡
面向过程 面向对象
1.自己去买菜 直接委托一个会做饭的人
2.自己处理材料
3.自己做菜
4.自己吃
案例二:小明是一个电脑小白,想要配置一台电脑
面向过程 面向对象
1.2面向对象和面向过程的区别
面向过程:
在生活案例中:一种看待问题的思维方式,在解决问题的时候,侧重于问题是怎样一步一步解决的,然后亲力亲为的去解决问题
在代码中:
代码从上往下依次执行【顺序结构】
各个模块之间的关系尽可能是独立的,当import的时候,加载的顺序也是从上往下依次加载
面向对象:
在生活案例中:一种看待问题的思维方式,在解决问题的时候,侧重于找到一个具有特殊功能的实体【个体】,然后委托这个个体帮忙完成某件事情,这个个体【实体】被称为对象
好处:可以将复杂的问题简单化,将程序员从执行者变成了一个指挥者
在代码中:
根据不同的需求执行代码【代码执行顺序不一定】
注意:面向对象只是一个思想,并不是一门编程语言
Python是一门面向对象的编程语言,类和对象是面向对象的核心
2.类和对象
2.1概念
类:多个具有特殊功能的个体的集合
对象:在 一个类中,一个具有特殊功能的个体,能够帮忙完成某件事情,也被称为实例【instance】
两者之间的关系:类用于描述某一类对象的特征,而对象是类的具体的存在
注意:在代码中,一般是先定义类,然后通过类创建对象
举例:
类 对象
人 张三,
快递 申通,圆通
帮助理解:类其实也是一种数据类型,只不过自定义的数据类型,用法和list,string等相同的
2.2类的定义和对象的创建
类的定义:
语法:
class 类名():
类体
说明:
a.Python中使用class关键字定义类
b.类名:只要是一个合法的标识符,要求:遵循大驼峰命名法
c.通过缩进区分类体
d.类体一般包含两部分内容:对类的特征的描述,对类的行为的描述
对象的创建:
语法:
变量名 = 类名()
num = 10
代码演示:
#类的定义【声明】 class MyClass(): #类的实现【类体】 pass #注意;在同一个py文件中可以同时定义多个类,但是,为了提高代码的可读性,结合模块的时候,最好能一个文件中定义一个类 class MyClass1(): pass #对象的创建 my = MyClass()
2.3类的设计
三要素:
事物名称【类名】,举例:人,Person
事物的特征【名词,变量】举例:姓名,年龄,身高。。。。
事物的行为【动词,函数/方法】举例:吃,跑....
3.类中的方法和变量
类中的方法和变量是为了描述类的行为和特征
类中的方法【函数】被称为成员方法
类中定义的变量被称为成员变量,也被称为属性【os.name】
3.1类中成员方法和成员变量的定义
代码演示:
#1.事物的名称:类名 class Person(): #2.事物的特征:成员变量/属性 name = "" age = 0 height = 0.0 #3.事物的行为:成员方法 #注意:类中的成员方法区别于普通方法:形参部分一定包含self,而且self最好出现在形参列表的第一个 #调用函数的时候,self不需要被传参 #除此之外,成员方法和普通方法的使用完全相同,也设置默认参数,关键字参数或者不定长参数 #self:自己,代表的是类的实例【对象】 #self在此处可以是任意的标识符,习惯上使用self def eat(self): print("eating") def run(self): print("running")
3.2类中成员方法和成员变量的使用
代码演示:
#一、类中成员方法和成员变量的定义 #1.事物的名称:类名 class Person(): #2.事物的特征:成员变量/属性 name = "5676" age = 0 height = 0.0 #3.事物的行为:成员方法 #注意:类中的成员方法区别于普通方法:形参部分一定包含self,而且self最好出现在形参列表的第一个 #调用函数的时候,self不需要被传参 #除此之外,成员方法和普通方法的使用完全相同,也设置默认参数,关键字参数或者不定长参数 #self:自己,代表的是类的实例【对象】 #self在此处可以是任意的标识符,习惯上使用self def eat(self,food): print("eating" + food) print("self的地址:",id(self)) def run(self): print("running",self.name) #二、类中成员方法和成员变量的使用【被访问】 #1.创建对象 #注意:通过类可以创建多个对象,不同的对象在内存中开辟了不同的空间 p1 = Person() p2 = Person() print(id(p1) == id(p2)) #False a = 10 b = 10 #p1和p2是变量名,称为对象,引用,指向了真正的实体【对象】 #2.访问成员变量【属性】 #语法:获取值:对象.属性名 重新赋值: 对象.属性名 = 新值 per = Person() print(per.name) per.name = "小姐姐" print(per.name) per.age = 10 per.height = 175.0 #3.调用成员方法 #语法:对象.函数名(实参列表) #注意1:self是系统自动传参的 #注意2:哪个对象调用了成员方法,则self代表的就是该对象【self表示当前对象】 per.eat("苹果") print("per的地址:",id(per)) p1.eat("香蕉") print("p1的地址:",id(p1)) """ eating苹果 self的地址: 2224407942536 per的地址: 2224407942536 eating香蕉 self的地址: 2224407942368 p1的地址: 2224407942368 """ #4.不同的对象访问同一个成员变量 per1 = Person() per2 = Person() print(id(per1) == id(per2)) #False #没有被重新赋值之前成员变量指向默认的实体 print(id(per1.name) == id(per2.name)) #True 其中的值都是5678 per1.name = "tom" per2.name = "jack" #重新赋值之后指向了新的实体,则地址跟着发生改变 print(per1.name,per2.name) print(id(per1.name) == id(per2.name)) #False del per1.name print(per1.name) #5678 print(per2.name) #结论:类中的成员变量和成员方法随着对象的出现而出现 per1.run() per1.name = "abc" per1.run()
3.3内存中的对象
per = Person()
per实际上是一个变量名,存储于栈空间中,它 指向了真正的对象,而真正的对象存储于堆空间中,成员变量随着真正的对象存储于堆空间中
3.4动态绑定属性和限制属性
Python是一门动态的语言,程序在运行的过程中,可以给对象动态绑定属性
代码演示:
#属性的动态绑定 class MyClass(): num1 = 0 num2 = 10 def fun1(self): print("fun1") def fun2(self,num): print("fun2",num) my = MyClass() my.num1 = 11 my.num2 = 22 print(my.num1,my.num2) my.fun1() my.fun2(30) #属性的动态绑定 #1.Python中可以给一个对象动态添加属性【属性时随着对象的出现而出现的】 my.num3 = 33 print(my.num3) #2.注意:动态添加的属性只能当前对象拥有,其他的对象无法使用 my1 = MyClass() #print(my1.num3) #报错:AttributeError: 'MyClass' object has no attribute 'num3' #思考问题:正因为能够动态绑定属性,而且动态添加的属性是没有限制的,为了避免这个问题的出现,使用__slots__ #限制属性 #__slots__变量:限制一个类中成员变量的个数和变量名称 #语法:__slots__ = ("属性1","属性2"。。。) class Test(): """ num1 = 0 num2 = 10 """ __slots__ = ("num1","num2") t1 = Test() #t1.num3 = 30 t1.num1 = 10
4.构造函数和析构函数
4.1构造函数【掌握】
构造函数也被称为构造器,当创建对象的时候第一个被自动调用的函数 per = Person() 语法: def __init__(self,arg1,arg2....): 函数体 说明: a.之前的写法中并没有显式的定义一一个构造函数,所以系统默认提供了一个无参的构造函数 b.arg1,arg2....,可以自己定义,但是,一般情况下,构造函数的形参列表和成员变量有关 c.构造函数的作用:创建对象,给对象的成员变量赋值代码演示:
#1.构造函数被调用的时机 class Check(): #成员变量 num1 = 0 s1 = "" #成员方法 def show(self): print("showing") #构造函数 def __init__(self): print("构造函数被执行了") c = Check() c.show() c.show() c.show() """ 构造函数和成员函数之间的区别 a.成员函数的函数名可以自定义,但是,构造函数的函数名是固定的,是__init__ b.成员函数需要被手动调用,但是,构造函数时在创建对象的过程中自动被调用的 c.对于同一个对象而言,成员函数可以被调用多次,但是,构造函数只能被调用一次 """ #2.给构造函数添加参数 class Check1(): #成员变量 num1 = 0 s1 = "" #成员方法 def show(self): print("showing") #构造函数 """ def __init__(self,n,s): print("构造函数被执行了") """ #不定长参数可以满足不同参数的需求 def __init__(self,*n): print("~~~~") #注意1:当在类中显式的定义了构造函数,并且给构造函数设置了参数,系统将不再提供无参的构造函数,所以创建对象的时候 #注意参数的匹配问题 #注意2:在同一个类中,构造函数只能出现一次 c1 = Check1(10,20) c2 = Check1() #3.构造函数的作用 class Check2(): #成员变量 num1 = 0 s1 = "" #成员方法 def show(self): print("showing") #构造函数 #构造函数的形参列表:一般和成员变量【主要给成员变量赋值】 def __init__(self,n,s): print(n,s) num1 = n s1 = s c3 = Check2(10,"abc") print(c3.num1,c3.s1) #4.self的使用 class Check3(): #成员变量 num1 = 0 s1 = "" #成员方法 def show(self): print("showing") #构造函数 #构造函数的形参列表:一般和成员变量【主要给成员变量赋值】 def __init__(self,n,s): print(n,s) #self的使用:通过self来区分成员变量和局部变量,所以self.num1代表num1 #并不是一个局部变量,而是一个成员变量 self.num1 = n self.s1 = s c4 = Check3(10,"abc") print(c4.num1,c4.s1) #5.使用self之后,可以省略成员变量的定义 class Check4(): # 成员方法 def show(self): print("showing") # 构造函数 def __init__(self, num1, s1): #定义了成员变量,成员变量赋初始值 self.num1 = num1 self.s1 = s1 c5 = Check4(22,"hello") print(c5.num1,c5.s1) #总结;一般情况下,在一个类中,包含构造函数和成员函数,在构造函数中,定义了成员变量并给成员变量赋值 #构造函数的形参:和成员变量有关