1.简述类属性和实例属性之间的区别
""" a.定义位置不同 b.访问方式不同 c.在内存中出现的时机不同【类属性优先于实例属性出现】 d.被对象访问的优先级不同【类属性和实例属性重名】 e.使用场景不同:类属性一般用于表示共享数据,实例属性用来表示对象的特有数据 """
2.简述成员函数,类函数和静态函数之间的区别
""" a.定义相同 b.类函数需要用@classmethod修饰,静态函数需要用@staticmethod修饰 c.参数:成员函数self,类函数cls,静态函数对参数不做要求 d.调用方式:类方法和静态方法都可以类名和对象调用,成员函数对象调用 e.在继承关系中,都可以被继承,都可以被重写 """
3.定义类,在类中分别定义一个成员函数,类函数和静态函数,实例化当前类对象并调用
class Check(object): def func1(self): pass @classmethod def func2(cls): pass #可以通过cls在当前类方法中创建对象,并且可以调用其他的函数 @staticmethod def func3(): pass c = Check() c.func1() c.func2() c.func3() Check.func2() Check.func3()
a.重写和重载
b.多态
定义时的类型和运行时的类型不一致【父类的引用指向子类的对象】
c.isinstance().结合if语句使用
d.类属性和实例属性
e.静态方法,类方法
单例:Singleton
春晚:小彩旗
问题:不管在哪个卫视上观看小彩旗,看到的都是同一个对象,为了节约内存,不管在哪个模块中获取,都应该获取的是同一个对象
解决:单例设计模式
person
class Person(object): # a.定义一个类属性,用来表示当前类的唯一的对象 instance = None # b.重载/重写__new__ def __new__(cls, *args, **kwargs): # 将当前类的实例跟instance类属性关联起来 # c.思路:如果instance为None,则给赋值【当前类的实例】;如果不为None,则将instance的值直接返回 if not cls.instance: # 创建对象并给instance赋值 cls.instance = super(Person, cls).__new__(cls, *args, **kwargs) return cls.instance # def __init__(self,name): # self.name = name def dance(self): print("dancing") print("hello")
test1
from singleton01.person import Person if __name__ != "__main__": print("浙江卫视") p = Person() print(id(p)) p.dance()
test2
from singleton01.person import Person if __name__ != "__main__": print("江苏卫视") p = Person() print(id(p)) p.dance()
test3
import singleton01.test1 import singleton01.test2 from singleton01.person import Person if __name__ == "__main__": print("中央卫视") p = Person() print(id(p)) p.dance()
设计模式:
是经过总结,优化的解决问题的可重用方案
将设计模式可以理解为一种解决问题的模板,设计模式不会绑定特定的编程语言
23种设计模式,其中比较常用的有单例设计模式,工厂设计模式,代理委托设计模式,生产者和消费者设计模式
单例设计模式:
程序在运行过程中,确保某个类只有一个实例【对象】,不管在哪个模块中进行获取,获取到的都是同一个实例【对象】,例如:一个国家只有一个国家主席
单例设计模式的核心:一个类有且仅有一个实例【对象】,并且该实例需要应用到整个项目中
Python中的模块本身就是一个天然的单例设计模式
import singleton01.person import singleton01.person import singleton01.person import singleton01.person #现象:虽然将自定义模块导入了四次,但是源文件只执行了一次 #模块的工作原理:因为模块在第一次导入的时候,在底层生成了文件.pyc文件,当第二次甚至第三次导入的时候,直接加载的是pyc文件,则不再执行原模块
#应用:只需将相关函数和数据定义在一个模块中,就可以获得一个单例对象,想要获取一个单例,则可以在模块中定义类 class Check(object): def foo(self): print("foo") instance = Check()
from singleton02.text1 import instance print(instance) instance.foo() """
foo """
__new__:创建对象的过程中自动调用的函数,优先于构造函数
#1.new的作用:从无到有的过程 class Person(object): def __init__(self): print("构造函数") def __new__(cls, *args, **kwargs): print("new") p = Person() #java中,p = new Person() #2.使用new实现单例设计模式:定义一个单例类 class Singleton(object): #a.定义一个类属性,用来表示当前类的唯一的对象 instance = None # b.重载/重写__new__ def __new__(cls, *args, **kwargs): # 将当前类的实例跟instance类属性关联起来 # c.思路:如果instance为None,则给赋值【当前类的实例】;如果不为None,则将instance的值直接返回 if not cls.instance: # 创建对象并给instance赋值 cls.instance = super(Singleton, cls).__new__(cls, *args, **kwargs) #1001 return cls.instance #只有第一次是在创建,其他都是在获取 #创建 s1 = Singleton() #获取 s2 = Singleton() print(id(s1) == id(s2))
#装饰器:作用于一个函数,也作用于类 #1.装饰器修饰函数 """ def wrapper(func): def inner(): func() #增加新的功能 return inner @wrapper def show(): pass show() """ #2.装饰器修饰类 #a。定义装饰器,外部函数的参数设置为cls,cls表示该装饰器需要装饰的类 def singleton(cls): """ 思路1:定义instance = None,,类似于new的用法 思路2:定义一个字典,以cls作为key,以cls创建的对象作为value存储到该字典中 """ #b.定义一个空字典 instance = {} #c。获取单例对象,命名:getinstance/currentInstance/defaultInstance def getInstance(*args,**kwargs): if cls not in instance: #字典[key] = value :如果key不存在,则表示向字典中添加了一对键值对 instance[cls] = cls(*args,**kwargs) return instance[cls] #1001 return getInstance @singleton class Text(object): def __init__(self,name,age): self.name = name self.age = age #创建 t1 = Text("jack",16) #获取 t2 = Text("bob",16) print(id(t1) == id(t2)) #总结:装饰器实现单例设计模式,除了当前类只能创建一个对象之外,其他的用法跟普通类的用法完全相同 #但是,通过new的方式实现单例,则对应的类的构造函数只能是无参的
#单例类 class Check(object): instsance = None #思路:给外界提供一个公开的函数,用于获取当前类的唯一的对象 @classmethod def getInstance(cls,*args,**kwargs): if not cls.instsance: cls.instsance = cls(*args,**kwargs) return cls.instsance """ c1 = Check() c2 = Check() print(id(c1) == id(c2)) """ c1 = Check.getInstance() c2 = Check.getInstance() print(id(c1) == id(c2))
Python中内置了文件读写的功能,面向对象化了
在磁盘上读写文件的功能是由操作系统提供的,现代操作系统不允许程序直接操作磁盘,所以,读写文件其实请求操作系统打开一个文件对象【通常称为文件描述符】,通过文件描述符作为接口从文件对象中读取数据,写入数据
普通文件:txt,图片,音视频等常用文件
过程:
a.打开文件:open(),返回一个文件对象
b.读取文件内容:read()/readline()
c.关闭文件:close()
#1.打开文件 """ open(path,flag[,encoding,errors]) path:要打开的文件的路径,一般使用相对路径 flag;打开方式 r:以只读的方式打开文件,一般用来打开txt普通文件 rb:以只读的方式打开二进制文件,一般用来打开图片,音视频文件 r+ :打开一个文件,用来读写 encoding:编码格式,一般常用gbk和utf-8【不区分大小写,utf-8也可以写成utf8】 errors:错误处理,一般不用,一旦有错误,使用异常处理:try-except """ #注意:读取文件的时候,必须保证读取的编码方式和文件本身的编码格式保持一致,否则乱码 #注意:open的返回值是被打开的文件的对象 f = open("致橡树.txt","r",encoding="gbk") #2.读取文件中的内容 #注意:默认情况下一次性读取全部的内容,如果文件内容过大的情况,则read函数会阻塞【卡顿】 result = f.read() print(result) #3.关闭文件 #作用:因为文件对象会占用内存空间,并且操作系统在同一时间内能够操作的文件数是有限的,关闭文件节约内存 f.close() #练习:读取file1.txt文件 f1 = open("file1.txt","r",encoding="utf-8") result1 = f1.read() print(result1) f1.close() """ 当以r的方式打开文件的时候,encoding到底需不需要加? 如果文件格式为gbk,可以不加encoding="gbk" 如果文件格式为utf-8,必须加encoding="utf-8",encoding关键字的默认值为gbk 如果rb的方式打开的文件时候,encoding一定不要加,加上会报错,直接写二进制形式, 通过字符串的encode编码,任何编码格式都可以 """ #f2 = open("fil1.txt","rb",encoding="utf-8") #ValueError: binary mode doesn't take an encoding argument #result2 = f2.read() #f2.close()
import os f1 = open("file1.txt","r",encoding="utf-8") #1.read(),如果不传参,则默认读取全部的内容 #result1 = f1.read() #2.read(num)读取指定字符数 #byte【字节】,一般情况下,num的值2的多少次方 """ result1 = f1.read(2) print(result1) result1 = f1.read(2) print(result1) result1 = f1.read(2) print(result1) #如果每次只是读取指定字节的数据,则需要通过循环实现 #文件中内容的多少,每次需要读取多少的内容 size = os.path.getsize("file1.txt") print(size) while size > 0: result1 = f1.read(16) print(result1) size -= 16 """ #3.readline();每次读取一行内容,通过换行符判断的"\n" #readline相比于read比较高效,读取文件的时候,如果文件的内容是以行的形式显示的,尽量采用readline """ result1 = f1.readline() print(result1) result1 = f1.readline() print(result1) result1 = f1.readline() print(result1) #每次读取一行,循环将所有的行全部读完 result1 = f1.readline() while result1: print(result1) result1 = f1.readline() #4.readline(num):读取一行内容的前num个字符,如果第二次调用,接着获取第一行的下num个字符,用法和read(num)完全相同的 result1 = f1.readline(5) print(result1) result1 = f1.readline(5) print(result1) """ #5.readlines():读取所有行,类似于read(),返回一个列表 #注意:每个元素的后面会有一个\n,内部的实现通过重复调用readline()实现的 #根据num和文本内容的比例显示的 # result1 = f1.readlines(100) # print(result1) f1.close() #掌握:read() read(1024) readline() #简写方式:with.....as # try: # pass # except TypeError as e: #好处:执行完自动close,避免忘记关闭资源造成的资源浪费 with open("file1.txt","r",encoding="utf-8") as f: print(f.read()) #with:上下文管理:通过某种方式简化异常,无论在什么时候出现异常,with都会在异常出现之前将文件自动关闭掉
a.打开文件:open()
b.写入数据:write()
c.刷新缓存:flush()
d。关闭文件:close()
#1.打开文件 """ flag: w:只能写入,表示覆盖原来的内容 wb:写入二进制文件 w+:读写的方式打开文件 a:append,表示在原来内容的后面进行追加 """ f = open("aaa.txt","a",encoding="utf-8") #2.写入内容 #write(字符串) #读取的时候由readline,但是写入的时候没有writeline,如果想要写入的内容可以换行,则手动添加\n f.write("hello") #3.刷新缓冲区,加速数据的流动,保证缓冲区的畅通,提高工作效率 f.flush() #4.关闭文件 f.close() #简写形式 with open("aaa.txt","a",encoding="utf-8") as f: f.write("fahjegh") f.flush()
字符串类型【str】和字节类型【bytes】之间的转换
由字符串类型转换为字节类型:编码,encode()
由字节类型转换为字符串类型:解码,decode()
注意:编解码的格式一定要保持一致,否则内容会乱码
#因为涉及到字节类型,使用二进制的方式打开文件:wb和rb #编码 path = r"file2.txt" with open(path,"wb") as f1: s = "today is a good day 今天是个好日子" #f1.write(s.encode("gbk")) f1.write(s.encode("utf-8")) f1.flush() #解码 with open(path,"rb") as f2: data = f2.read() print(data) print(type(data)) newData = data.decode("utf-8") print(newData) print(type(newData))
1.拷贝图片
#需求:实现图片【音视频】的拷贝 def main(): try: with open("dog.jpg","rb") as f1: data = f1.read() #print(data) with open("image/dog.jpg","wb") as f2: f2.write(data) f2.flush() except FileNotFoundError as e: print(e,"文件路径不存在") except IOError as e: print(e,"读写过程中提前关闭文件") if __name__ == "__main__": main()
2.拷贝文件
import os """ 1、拷贝文件内容,考虑大文件拷贝 每次读取1024字节拷贝 """ #src_path,:被读取的文件 【必须存在】 #des_path:被写入文件【可以不存在】 def mycopy(src_path,des_path): #判断源文件是否存在,如果不存在,则拷贝不了 if not os.path.exists(src_path): print("源文件不存在,无法拷贝") return #判断源路径是否是文件,如果是目录,则拷贝不了 if not os.path.isfile(src_path) or not os.path.isfile(des_path): print("源路径或者目标路径是文件夹,无法拷贝") return #打开源文件和目标文件 srcFile = open(src_path,"rb") desFile = open(des_path,"wb") #读取src_path中的内容,将内容写入到des_path中 size = os.path.getsize(src_path) subSize = 1024 while size > 0: content = srcFile.read(subSize) desFile.write(content) desFile.flush() size -= subSize srcFile.close() desFile.close()
3.邮编查询
""" 2、邮编查询 查到返回对应的城市 否则提示无此邮编 """ num = input("请输入邮编:") if num.isdigit() and len(num) == 6: path = r"youbian.txt" # 读取文件中的内容 f = open(path, "r", encoding="utf-8") line = f.readline() # 如果有内容,则返回内容,如果没有内容,则返回None # print(line) # [110221,"北京市昌平县"], while line: newStr = line[1:] # 110221,"北京市昌平县"], if newStr.startswith(num): newStr = newStr[8:-4] # 北京市昌平县"], print(newStr) # 如果查询的过程中,提前找到了符合条件的城市,则可以提前结束循环 break # 继续读取后面的内容,给line重新赋值 line = f.readline()
4.开房记录
""" 3、开房查询 输入名字,查询其开房记录,如果没有,是一个单纯哥们,如果有的话,将其所有开房信息写入到以这哥们命名的文件中 """ #第一步:读取文件 def loadFile(path): f = open(path,"r",encoding="utf-8") #readlines返回一个列表 lt = f.readlines() f.close() return lt #第二步:查询 #思路:根据名字查询开房记录,如果有,则将被查询的人的所有信息生成一个新的列表 def search(personList,name): subList = [] #遍历所有人的列表 #line表示每个人的详细信息 for line in personList: #使用逗号将每个人的信息分隔 infoList = line.split(",") if name == infoList[0]: subList.append(line) #如果没有查找到信息,则返回[] #如果找到,返回[被查询的人的信息] return subList if __name__ == "__main__": path = r"kaifanglist.txt" allList = loadFile(path) #print(allList) while True: message = input("请输入需要查找的人的姓名【输入q退出】:") if message == "q": break else: #获取被查询的人的信息 singleList = search(allList,message) if singleList: print(message + "果然去开房了") #将信息写入到以message命名的文件中 file = open(message + ".txt","a",encoding="utf-8") for subLine in singleList: file.write(subLine) file.flush() file.close() print("数据提取成功") else: print(message + "是一个好人")