Day9

一、上堂回顾

1.默写题目

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()

2.知识点回顾

a.重写和重载

b.多态

​ 定义时的类型和运行时的类型不一致【父类的引用指向子类的对象】

c.isinstance().结合if语句使用

d.类属性和实例属性

e.静态方法,类方法

二、单例设计模式

1.案例

单例: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()

2.概念

设计模式:

​ 是经过总结,优化的解决问题的可重用方案

​ 将设计模式可以理解为一种解决问题的模板,设计模式不会绑定特定的编程语言

​ 23种设计模式,其中比较常用的有单例设计模式,工厂设计模式,代理委托设计模式,生产者和消费者设计模式

单例设计模式:

​ 程序在运行过程中,确保某个类只有一个实例【对象】,不管在哪个模块中进行获取,获取到的都是同一个实例【对象】,例如:一个国家只有一个国家主席

​ 单例设计模式的核心:一个类有且仅有一个实例【对象】,并且该实例需要应用到整个项目中

3.使用

3.1模块

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
"""
3.2使用new
__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))

3.3使用装饰器
#装饰器:作用于一个函数,也作用于类
#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的方式实现单例,则对应的类的构造函数只能是无参的
3.4自定义类实现
#单例类
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中内置了文件读写的功能,面向对象化了

在磁盘上读写文件的功能是由操作系统提供的,现代操作系统不允许程序直接操作磁盘,所以,读写文件其实请求操作系统打开一个文件对象【通常称为文件描述符】,通过文件描述符作为接口从文件对象中读取数据,写入数据

1.普通文件读写

普通文件:txt,图片,音视频等常用文件

1.1读文件

过程:

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都会在异常出现之前将文件自动关闭掉
1.2写文件

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()
1.3编码和解码

字符串类型【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.4练习

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 + "是一个好人")

你可能感兴趣的:(Day9)