• python (五)小数据池、集合、copy、文件操作


    一、编码进阶

    # 字符串转换成bytes型
    s1 = 'taibai'
    s2 = b'taibai' # 默认的str是(py2.x里的)unicode, bytes是(py2.x)的str, b+字符串代表的就是bytes 
    
    
    # 将字符串的第一个字母变成大写,其他字母变小写
    s1 = b'lily'
    print(s1.capitalize())
    
    
    # 编码
    str ---> bytes  编码 encode()
    s1 = 'alex'
    b1 = s1.encode('utf-8')  # 编码
    b2 = s1.encode('gbk')
    print(s1, type(s1))
    print(b1, type(b1))
    print(b2, type(b2))
    
    # 解码
    s1 = '猪八戒'
    b1 = s1.encode('utf-8')
    b2 = s1.encode('gbk')
    print(s1,b1)
    print(s1,b2)
    
    bytes ---> str  decode()解码
    b1 = b'xe5xa4xaaxe7x99xbd'
    s1 = b1.decode('gbk')
    print(s1)

    二、小数据池

    1. id  查看内存地址

    s1 = '太白'
    s2 = '太白'
    print(s1 == s2)  # 值是否相等
    print(id(s1))
    print(id(s2))# 内存地址

    2. is 身份运算 判断的是内存地址是否相同

    s1 = '太白'
    s2 = '太白'
    print(s1 is s2) # 判断内存地址是否相等

    3. 小数据池

    i1 = -3
    int: -5 ~ 256 范围之内
    str: 满足一定得规则的字符串(详见博客https://www.cnblogs.com/jin-xin/articles/9439483.html)
    
    小数据池的优点:
    1,节省空间。
    2,提高性能。

    三、集合

      集合里面的元素必须是不可变的数据类型,集合本身是可变的数据类型。

      集合是无序的,不重复。

    print({[1, 2, 3], {'name': 'lily'}})
    print({'lily', 'marry', 'tony', '老猪', 'AnNi'})

     

    1、 列表去重。  

    l1 = [1, 1, 2, 3, 4, 3, 2, 4, 5, 6]
    set1 = set(l1)  # 
    print(set1)  # {1, 2, 3, 4, 5, 6}
    l1 = list(set1)
    print(l1)  # [1, 2, 3, 4, 5, 6]

    2、关系测试。

    set1 = {'lily', 'marry', 'tony', '老猪', 'AnNi'}
    for i in set1:
        print(i)

     

    3、不可变的数据类型

    set2 = frozenset({1, 2, 3, 7})  # frozenset() 返回一个冻结的集合,冻结后集合不能再添加或删除任何元素
    print(set2, type(set2))  # 不可变的数据类型
    dic = {set2: 666}
    print(dic)
    for i in set2:
        print(i)

     

    4、集合的增删改查

    # 1、集合的创建
    set1 = set({1, 2, 'barry'})
    set2 = {1, 2, 'barry'}
    print(set1, set2)  # 结果为:{1, 2, 'barry'} {1, 2, 'barry'}
    
    # 2、集合的增
    set1 = {'alex', 'wusir', 'ritian', 'egon', 'barry'}
    set1.add('景女神')
    print(set1)
    
    # 3、update:迭代着增加
    set1.update('A')
    print(set1)
    set1.update('老师')
    print(set1)
    set1.update([1, 2, 3])
    print(set1)
    
    # 4、集合的删
    set1 = {'alex', 'wusir', 'ritian', 'egon', 'barry'}
    
    set1.remove('alex')  # 删除一个元素
    print(set1)
    
    set1.pop()  # 随机删除一个元素
    print(set1)
    
    set1.clear()  # 清空集合
    print(set1)
    
    del set1  # 删除集合
    print(set1)
    
    # 5、集合的计算
    set2 = {4, 5, 6, 7, 8}
    set1 = {1, 2, 3, 4, 5}
    print(set2 - set1)  # {8, 6, 7} 只输出set2中比set1中多余的部分
    print(set1.difference(set2))  # {1, 2, 3} 只输出set1中比set2中多余的部分

    5、集合的其他操作:

    # 1、交集
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 8}
    print(set1 & set2)  # {4, 5}
    print(set1.intersection(set2))  # {4, 5}
    
    # 2、并集。(| 或者 union)
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 8}
    print(set1 | set2)  # {1, 2, 3, 4, 5, 6, 7,8}
    print(set2.union(set1))  # {1, 2, 3, 4, 5, 6, 7,8}
    
    # 3、差集。(- 或者 difference)
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 8}
    print(set1 - set2)  # {1, 2, 3}
    print(set1.difference(set2))  # {1, 2, 3}
    
    # 4、反交集。 (^ 或者 symmetric_difference)
    set1 = {1, 2, 3, 4, 5}
    set2 = {4, 5, 6, 7, 8}
    print(set1 ^ set2)  # {1, 2, 3, 6, 7, 8}
    print(set1.symmetric_difference(set2))  # {1, 2, 3, 6, 7, 8}
    
    # 5、frozenset 不可变集合,让集合变成不可变类型。
    s = frozenset('barry')
    print(s, type(s))  # frozenset({'a', 'y', 'b', 'r'}) <class 'frozenset'>

    四、深浅copy

    1、赋值运算

    l1 = ['alex', '女神',]
    l2 = l1  # 赋值运算
    l1.append('日天')
    print(l1, id(l1))  # ['alex', '女神', '日天'] 4348215176
    print(l2, id(l2))  # ['alex', '女神', '日天'] 4348215176
    #  赋值运算是相同的内存地址

    2、浅copy 第一层开辟的新的内存地址,但是从第二层乃至更深的层来说,公用的都是一个。

    l1 = [1, 2, 3, ['大锤', '悟空']]
    
    l2 = l1.copy()  # 不同的内存地址
    print(l1, id(l1))  # [1, 2, 3, ['大锤', '悟空']] 4399517640
    print(l2, id(l2))  # [1, 2, 3, ['大锤', '悟空']] 4400231496
    
    
    l1[1] = 222  # 第一层是不同的内存地址
    print(l1, id(l1))  # [1, 222, 3, ['大锤', '悟空']] 4399517640
    print(l2, id(l2))  # [1, 2, 3, ['大锤', '悟空']] 4400231496
    
    l1[3][0] = 'wusir'  # 第二层是相同的内存地址
    print(l1, id(l1[3]))  # [1, 222, 3, ['wusir', '悟空']] 4399517576
    print(l2, id(l2[3]))  # [1, 2, 3, ['wusir', '悟空']] 4399517576

    小总结: 

    对于浅copy来说,第一层创建的是新的内存地址,而从第二层开始,指向的都是同一个内存地址,所以,对于第二层以及更深的层数来说,保持一致性。

    3、深拷贝deepcopy

    import copy
    l1 = [1, 2, 3, ['悟空', '大锤']]
    
    l2 = copy.deepcopy(l1)  # 不同的内存地址
    print(l1, id(l1))  # [1, 2, 3, ['悟空', '大锤']] 4421605128
    print(l2, id(l2))  # [1, 2, 3, ['悟空', '大锤']] 4421812104
    
    l1[1] = 222  # 不同的内存地址
    print(l1, id(l1))  # [1, 222, 3, ['悟空', '大锤']] 4421605128
    print(l2, id(l2))  # [1, 2, 3, ['悟空', '大锤']] 4421812104
    
    l1[3][0] = 'wusir'  # 不同的内存地址
    print(l1, id(l1[3]))  # [1, 222, 3, ['wusir', '大锤']] 4421606472
    print(l2, id(l2[3]))  # [1, 2, 3, ['悟空', '大锤']] 4421845320

    小总结:

    对于深copy来说,两个是完全独立的,改变任意一个的任何元素(无论多少层),另一个绝对不改变。

    五、文件操作

    1、文件操作的流程

    #  1. 打开文件,得到文件句柄并赋值给一个变量
    f=open('a.txt','r',encoding='utf-8')  
    # 打开模式就为r,open()是内置函数,用来操作文件
    # f是文件句柄f1,fh,file_handle,f...都可以作为文件句柄
    
    #  2. 通过句柄对文件进行操作读,写,追加,读写...)
    data=f.read()  # data是str类型
    
    #  3. 关闭文件句柄,即关闭文件
    f.close()

    2、关闭文件的注意事项

    打开一个文件包含两部分资源:操作系统级打开的文件 + 应用程序的变量。
    在操作完毕一个文件时,必须把与该文件的这两部分资源一个不落地回收,回收方法为:
    1、f.close()  # 回收操作系统级打开的文件
    2、del f  # 回收应用程序级的变量
    
    其中del f一定要发生在f.close()之后,否则就会导致操作系统打开的文件还没有关闭,白白占用资源,
    而python自动的垃圾回收机制决定了我们无需考虑del f,这就要求我们在操作完毕文件后,一定要记住f.close()
    
    虽然我这么说,但是很多同学还是会忘记f.close(), 所以我们推荐傻瓜式操作方式:使用with关键字来帮我们管理上下文
    with open('a.txt', 'w') as f:
        pass
    
    with open('a.txt', 'r') as read_f, open('b.txt', 'w') as write_f:
        data = read_f.read()
        write_f.write(data)

    3、文件的编码

    f=open(...)是由操作系统打开文件,那么如果我们没有为open()指定编码,那么打开文件的默认编码很明显是操作系统说了算了,操作系统会用自己的默认编码去打开文件,在windows下是gbk,在linux下是utf-8。

    # 若要保证不乱码,文件以什么方式存的,就要以什么方式打开。
    f=open('a.txt','r',encoding='utf-8')

    4、文件的打开模式

    # 1. 打开文件的模式有(默认为文本模式):
    r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
    w,只写模式【不可读;不存在则创建;存在则清空内容】
    a, 只追加写模式【不可读;不存在则创建;存在则只追加内容】
    
    # 2. 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作
    #   (而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式)
    rb 
    wb
    ab
    注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码
    
    # 3,‘+’模式(就是增加了一个功能)
    r+, 读写【可读,可写】(删除以前的所有数据)
    w+,写读【可写,可读】
    a+, 写读【可写,可读】
    
    # 4,以bytes类型操作的读写,写读,写读模式
    r+b, 读写【可读,可写】
    w+b,写读【可写,可读】
    a+b, 写读【可写,可读】

    5、文件的常用操作方法

      5-1、文件操作--读(r)   

    # r  只读模式
    # 第一种 read() 全部读取
    f1 = open('a.txt', encoding='utf-8')  # 默认的打开方式是r,可以不用写
    content1 = f1.read()  # 读取全部的文件内容,str类型
    print(content1)
    f1.close()
    
    
    # 第二种 read(n)  打开模式为文本时按照字符去读取,打开方式为b模式时,代表读取3个字节
    f1 = open('a.txt', encoding='utf-8')  # 原文件内容为:王大锤啊
    content2 = f1.read(3)  # 只读取前三个字符
    print(content2)  # 结果为:王大锤
    f1.close()
    
    f1 = open('a.txt',  mode='rb')  # 原文内容为: 12345,b模式打开的不能规定编码格式
    content1 = f1.read(3)  # 按照字节读取前三个字符
    print(content1)  # 结果为:b'123' ,表示b方式的结果为123
    f1.close()
    
    
    # 第三种 readline() 按行读取,无内容输出空。
    # readline(n)  读取当前行的前n个字符
    f1 = open('a.txt', encoding='utf-8')
    print(f1.readline().strip())  # 读取第一行
    print(f1.readline().strip())  # 读取第二行
    print(f1.readline().strip())  # 读取第三行,第三行无内容,当前行就为空
    print(f1.readline(3).strip())  # 读取第四行的前三个字符
    f1.close()
    print(666)  # 在关闭文件后再次输出
    
    
    # 第四种 readlines() 返回一个列表,列表中的每个元素是原文件的一行
    # readlines(n) 从文件中读取前n个字符,只返回这n个字符所在的字符串
    f1 = open('a.txt', encoding='utf-8')
    # 文件内容会以单行为一个元素,存储成一个列表,每个元素是字符串格式,
    # 行末换行以
    的格式存储在这一行的所在的元素中,如['1234
    ', 'qwer
    ']
    content3 = f1.readlines()
    print(content3)  # content为list格式
    f1.close()
    
    # readlines(n) 加参数的例子
    f1 = open('a.txt', encoding='utf-8')
    content4 = f1.readlines(4)  # ['1234
    '],只输出前四个字符所在行的字符串
    content5 = f1.readlines(5)  # ['1234
    ', 'qwer
    '],输出前5个字符所在行的字符串,不包含换行
    print(content4)
    print(content5)
    f1.close()
    
    
    # 第五种 for循环,循环输出每行的内容
    f1 = open('a.txt', encoding='utf-8')
    for line in f1:  # 依次读取每行
        print(line.strip())  # 去掉每行头尾空白
    f1.close()
    
    # for 循环的第二种方法,借助readlines
    f1 = open('a.txt', encoding='utf-8')
    for line in f1.readlines():  
        print(line.strip())
    f1.close()
    
    
    # 第六种  rb 按照二进制位进行读取
    f1 = open('b.jpg', mode='rb')  # 读取图片文件b.jpg
    content6 = f1.read()
    print(content6, type(content6))  # byte类型
    f1.close()
    
    
    # 第七种  wb 按字节的方式写如 (此例是读取其他图片内容,并写入新文件)
    f1 = open('b.jpg', mode='rb')
    content7 = f1.read()
    f2 = open('c.jpg', mode='wb')
    f2.write(content7)  # 或者可以写成f2.write(f1.read())读取f1文件的内容,写入f2(即复制图片并重命名)
    f1.close()
    f2.close()
    
    
    # 第八种  r+ 先读后写(后追加)
    f1 = open('a.txt', encoding='utf-8', mode='r+')
    content8 = f1.read()  # 先以读的方式打开文件
    f1.write('666')  # 写入文件内容666,此处没有换行,所以写入的位置是在原文件最后一行的末尾
    f1.write('
    来了')  # 加了
    , 会在原来文件的最后一行后换行再输入内容
    print(f1.read())
    f1.close()

      

      5-2、文件操作--写(w)   

    # w  只写模式【不可读;不存在则创建;存在则清空内容】
    # 1,没有文件创建文件写入内容。
    # 2,有文件先清空后写入。
    f1 = open('a.txt', encoding='utf-8', mode='w')
    f1.write('又好了...')
    f1.close()

      5-3、文件操作--追加(a)  

    # a 只追加写模式【不可读;不存在则创建;存在则只追加内容】
    # 1,没有文件创建文件写入内容。
    # 2,有文件直接在后面追加。
    f1 = open('a.txt', encoding='utf-8', mode='a')
    f1.write('
    喇叭坏了 fuck')
    f1.close()

      

      5-4、文件操作常用的方法  

    # readable() 检查指定的文件是否可读,如果文件可读,readable()这个函数返回True,否则返回False
    f1 = open('log1', encoding='utf-8', mode='w')  # 前提:没有log1文件
    if f1.readable():  # 判断文件是否可读
        print(f1.read())   # 如果可读,输出文件内容
    print(f1.readable())  # 如果不可读,返回readable()这个函数的值:True或False
    f1.close()
    
    
    # writable() 检查指定的文件是否可写,如果文件可写,readable()这个函数返回True,否则返回False
    f1 = open('log1', encoding='utf-8', mode='w')  # 前提:没有log1文件
    if f1.writable():  # 判断文件是否可写
        pass   # 如果可写,pass
    print(f1.writable())  # 如果不可写,先创建文件,再返回writable()这个函数的值:True或False
    f1.close()
    
    
    # tell() 告诉你光标的位置(按照字节),换行也算
    f1 = open('a.txt', encoding='utf-8')
    content = f1.read()  # 全部读取
    print(f1.tell())  # 因为是全部读取,所以当前光标所在位置是文件的最后一个字符后一个位置
    f1.close()
    
    f1 = open('a.txt', encoding='utf-8')
    content1 = f1.read(3)  # 读取前三个字符
    print(f1.tell())  # 只读取前三个字符,所以当前光标所在位置是第三个字符的位置,结果为3
    f1.close()
    
    
    # seek() 调整光标的位置(按照字节),输出当前字节后的文件内容,换行符也算,后边无内容不会报错
    f1 = open('a.txt', encoding='utf-8')  # 原文件内容为qwerty
    f1.seek(4)  # 原光标位置在文件开头,现在调整到文件第四个字符的位置,即光标所在位置为r
    content2 = f1.read()
    print(content2)  # 结果为ty
    f1.close()
    
    
    
    # fileno 件描述符
    # flush 刷新文件内部缓冲区
    # isatty 判断文件是否是同意tty设备
    f1 = open('a.txt', encoding='utf-8')
    content1 = f1.fileno()
    content2 = f1.flush()
    content3 = f1.isatty()
    print(content1)
    print(content2)
    print(content3)
    f1.close()
    
    # readinto 读取到缓冲区,不要用,将被遗弃
    # truncate(self, size=None): 截断数据,文件内容仅保留指定之前数据
    f1 = open('a.txt', 'r+')  # 因为需要读且修改,所以是r+,原文件内容为qwer
    f1.truncate(3)  # 截取到第3个字符
    content4 = f1.read() # 读取截取完的文件
    print(content4)  # 结果为qwe,文件内容被更改成qwe
    f1.close()
    
    # write 写入指定字符串,原文件内容会被删除
    f1 = open('a.txt', 'w')
    f1.write('大锤')  # 原文件内容被删除,内容只有:大锤
    f1.close()
    
    # writelines  按写入指定字符串,原文件内容会被删除
    f1 = open('a.txt', 'w')
    seq = ['第一行
    ', '第二行
    ', '第三行']  # 将参数直接赋值给字符串
    f1.writelines(seq)  # 读取这个列表,列表中的每个元素是这个文件中的一行
    f1.close()

       5-5、修改文件的方法  

      修改文件不一定是追加,所以w的操作不适用修改

    '''
      修改一个文件的方法:
            1,以读的模式打开原文件
            2,以写的模式打开一个新文件
            3,对原文件的内容进行修改,形成新内容写入新文件
            4,删除原文件
            5,将新文件重命名为原文件。
    '''
    
    # 第一种read() 直接读取原文件全部内容,占用内存
    import os
    with open('a.txt', encoding='utf-8') as f1, 
            open('b.txt', encoding='utf-8', mode='w') as f2:  # 以读的方式打开原文件a,以写的方式打开新文件b
        old_content = f1.read()  # 读取原文件内容,全部存入内存
        new_content = old_content.replace('123', 'SB')  # 对原文件内容进行修改
        f2.write(new_content)  # 将修改后的内容写入新文件
    os.remove('a.txt')  # 删除相对路径下的原文件,如果是绝对路径,要写上路径
    os.rename('b.txt', 'a.txt')  # 将新文件的名字命名为原文件,原文件会被删除,相当于新文件覆盖了原文件
    
    
    # 第二种用for循环读取文件内容,节省内存
    import os
    with open('a.txt', encoding='utf-8') as f1, 
            open('b.txt', encoding='utf-8', mode='w') as f2:
        for line in f1:  # 循环读取每一行,一行一行存入内存
            new_line = line.replace('SB', '123')  # 如果读取到这一行内容有SB,则替换成123
            f2.write(new_line)  # 把新修改的行写入到文件2
    os.remove('a.txt')  # 删除原文件
    os.rename('b.txt', 'a.txt')  # 新文件覆盖了原文件,并命名为原文件的名字

      

    课后练习

    '''
    1. 文件a1.txt内容
    
        序号     部门      人数      平均年龄      备注
        1       python    30         26         单身狗
        2       Linux     26         30         没对象
        3       运营部     20         24         女生多
        .......
        通过代码,将其构建成这种数据类型:
        [{'序号':'1','部门':Python,'人数':30,'平均年龄':26,'备注':'单身狗'},......]
    '''
    
    
    lis = []
    f = open('/Users/chensihan/Documents/shanshan/作业/a1.txt', encoding='utf-8', mode='r')
    content = f.readline()
    n = content.split()
    x = 0
    for i in f:
        dic = {}
        m = i.strip().split()
        for x in range(len(m)):
            dic[n[x]] = m[x]
            x += 1
        lis.append(dic)
    print(lis)
    f.close()
    
    
    # 第二种
    li = []
    with open('/Users/chensihan/Documents/shanshan/作业/a1.txt', encoding='utf-8', mode='r') as f:
        key = f.readline().strip().split()
        # 先读取第一行作为key键的列表元素
        # 此时光标己移到第2行开头,再进行后面同样是行循环
        # print(key)  # ['序号', '部门', '人数', '平均年龄', '备注']
        for line in f:
            val = line.strip().split()
            # 以key为基准,循环i次去进行zip函数两个列表合并成字典的操作就简单了
            # print(val) # ['1', 'python', '30', '26', '单身狗'] ['2', 'Linux', '26', '30', '没对象'] ['3', '运营部', '20', '24', '女生多']
            dic = dict(zip(key, val))
            li.append(dic)
    print(li)
    
    '''
    2. 计算传入函数的字符串中,[数字]、[字母]、[空格] 以及 [其他]的个数,并返回结果。
    '''
    
    str = input('请输入字符串:')
    
    
    def count(str):
        digit_num = 0
        alpha_num = 0
        space_num = 0
        other_num = 0
        for i in str:
            if i.isdigit():  # 判断是否是数字
                digit_num += 1
            elif i.isalpha():  # 判断是否是字母
                alpha_num += 1
            elif i.isspace():  # 判断是否是空格
                space_num += 1
            else:
                other_num += 1
        return ('其中数字有%s个,字母有%s个,空格有%s个,其他有%s个。' % (digit_num, alpha_num, space_num, other_num))
    
    
    print(count(str))
    
    '''
    3. 写函数,接收两个数字参数,返回比较大的那个数字。
    '''
    # 方法一
    num1 = input('请输入第一个数字:').strip()
    num2 = input('请输入第二个数字:').strip()
    
    
    def comparison(*args, **kwargs):
        if num1 > num2:
            return num1
        else:
            return num2
    
    print(comparison(num1, num2))
    
    # 方法二
    num1 = input('请输入第一个数字:').strip()
    num2 = input('请输入第二个数字:').strip()
    
    
    def comparison(a, b): return a if a < b else b
    
    
    print(comparison(num1, num2))
    '''
    4. 写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
        dic = {"k1": "v1v1", "k2": [11,22,33,44]}
        PS:字典中的value只能是字符串或列表
    '''
    dic = {"k1": "v1v1", "k2": [11, 22, 33, 44]}
    
    
    def check(dict):
        dic_new = {}
        for key, values in dic.items():
            dic_new[key] = values[:2]
        
        return dic_new
    
    
    print(check(dic))
    
    '''
    5. 写函数,此函数只接收一个参数且此参数必须是列表数据类型,
       此函数完成的功能是返回给调用者一个字典,此字典的键值对为此列表的索引及对应的元素。
       例如传入的列表为:[11,22,33] 返回的字典为 {0:11,1:22,2:33}。
    '''
    
    # 方法一
    dic = {}
    lis = [11, 22, 33]
    
    def func(list):
        for i, j in enumerate(lis, 0):
            # print(i, j)  # 循环输出三行,第一行0 11,第二行1 22,第三行2 33
            dic[i] = j
            i += 1
        return dic
    
    print(func(lis))
    
    # 方法二
    dic = {}
    lis = [11, 22, 33]
    
    def func(lis):
        i = 0
        for value in lis:
            dic[i] = value
            i += 1
        return dic
    
    print(func(lis))
    
    '''
    6. 写函数,函数接收四个参数分别是:姓名,性别,年龄,学历。用户通过输入这四个内容,
       然后将这四个内容传入到函数中,此函数接收到这四个内容,将内容追加到一个student_msg文件中。
    '''
    name = input('姓名:')
    sex = input('性别:')
    age = input('年龄:')
    xueli = input('学历:')
    
    
    def stu(name, sex, age, xueli):
        with open('/Users/chensihan/Desktop/student_msg.txt', encoding='utf-8', mode='w') as f:
            f.write('姓名:%s, 性别:%s, 年龄:%d, 学历:%s' % (name, sex, int(age), xueli))
        print('输入成功')
    
    stu(name, sex, age, xueli)
    
    
    
    '''
    7. 对第6题升级:支持用户持续输入,Q或者q退出,性别默认为男,如果遇到女学生,则把性别输入女。
    '''
    
    
    def stu(name, age, xueli, sex=''):
    
        with open('/Users/chensihan/Desktop/student_msg.txt', encoding='utf-8', mode='a') as f:
            f.write('
    姓名:%s, 年龄:%d, 学历:%s, 性别:%s' % (name, int(age), xueli, sex))
            return
    
    while 1 == 1:
            name = input('
    ' + '请输入姓名(输入q或Q退出):').strip()
            if name.strip().upper() == 'Q': break
            else:
                age = input('请输入年龄:').strip()
                xueli = input('请输入学历:').strip()
                sex = input('请输入性别(如果为男,输入1即可):').strip()
                if sex == '':
                    stu(name, age, xueli, sex)
                else:
                    stu(name, age, xueli)
            print('输入成功')
    
    
    '''
    8. 写函数,用户传入要修改的文件名与要修改的内容,执行函数,完成整个文件的批量修改操作。
    '''
    import os
    # 以读的方式打开原文件,以写的方式打开新文件
    with open('/Users/chensihan/Desktop/原文件.txt', encoding='utf-8', mode='r') as f1, 
            open('/Users/chensihan/Desktop/新文件.txt', encoding='utf-8', mode='w') as f2:
        for line in f1:  # 循环读取原文件内容
            new_line = line.replace('原来的内容', '修改后的新内容')  # 新文件中相应位置被修改
            f2.write(new_line)  # 将修改后的行追加到新文件中
    os.remove('/Users/chensihan/Desktop/原文件.txt')  # 删除原文件
    os.rename('/Users/chensihan/Desktop/新文件.txt', '/Users/chensihan/Desktop/原文件.txt')  # 将新文件覆盖到原文件的位置
    print('修改成功')
    
    '''
        读代码,回答:代码中,打印出来的值a,b,c分别是什么?为什么?
    a=10
    b=20
    def test5(a, b):
                    print(a, b)
    c = test5(b, a)
    print(c)
    '''
    a = 10
    b = 20
    
    
    def test5(a, b):
                    print(a, b)  # 执行完函数,输出函数的执行结果a= 20, b=10
    
    
    c = test5(b, a)  # 调用函数, 将值b = 20 传给a, 将a = 10传给b,
    
    
    print(c)  # c=test5,test5函数执行的结果未return回来值,所以执行结果是 none,
    
    '''
    9. 读代码,回答:代码中,打印出来的值a,b,c分别是什么?为什么?
        a=10
        b=20
        def test5(a,b):
        a=3
        b=5
        print(a,b)
        c = test5(b,a)
        print(c)
    '''
    
    a = 10
    b = 20
    def test5(a, b):
        a = 3  # 将a = 3 传给a
        b = 5  # 将b = 5传给b
        print(a, b)  # 执行完函数,输出函数的执行结果a = 3, b = 5
    print(a, b)  # a = 10 b = 20
    c = test5(b, a)  # 调用函数,函数内部有值,使用内部值
    print(c)  # c=test5,test5函数执行的结果未return回来值,所以执行结果是 none,
    
    '''
    10. 写函数,传入函数中多个实参(均为可迭代对象如字符串,列表,元祖,集合等),
        将每个实参的每个元素依次添加到函数的动态参数args里面.
        例如 传入函数两个参数[1,2,3] (22,33)最终args为(1,2,3,22,33)
    '''
    lis = [1, 2, 3]
    tup = (22, 33)
    
    def func(*args):  # *args接收除字典外其他类型的值
        print(args)
    
    func(*lis, *tup)  # 将传入的参数打散后再传给*args
    
    '''
    11. 写函数,传入函数中多个实参(实参均为字典),将每个实参的键值对依次添加到函数的动态参数kwargs里面.
        例如 传入函数两个参数{‘name’:’alex’} {‘age’:1000}最终kwargs为{‘name’:’alex’ ,‘age’:1000}
    '''
    dic1 = {'name': 'alex'}
    dic2 = {'age': 1000}
    
    
    def func(**kwargs):  # **kwargs只接收字典类型的值
        print(kwargs)
    
    
    func(**dic1, **dic2)  # 将参数打散再传给**kwargs
    
    '''
    12. 下面代码成立么?如果不成立为什么报错?怎么解决?
    题目一:
    '''
    a = 2
    def wrapper():
        print(a)  # 成立,调用外部值 ,输出a的值为2
    wrapper()
    
    '''
    题目二:
    '''
    a = 2
    def wrapper():
        # global a  # 增加代码,使用global 可以调用并修改全局变量
        a += 1  # 不成立,函数局部不能修改全局变量,只能调用
        print(a)
    wrapper()
    '''
    题目三:
    '''
    def wrapper():
        a = 1
    
        def inner():
            print(a)  # 成立,调用外部值 ,输出a的值为1
    
        inner()
    
    
    wrapper()
    '''
    题目四:
    '''
    
    def wrapper():
        # global a  # 增加代码,使用globa声明全局变量a
        a = 1  # a属于函数内部的值,无法被inner函数引用
    
        def inner():
            # global a  # 增加代码,使用global引用外部的a的值
            a += 1  # 此处a无值
            print(a)  # 不成立
        inner()
    wrapper()
    
    '''
    13. 写函数,接收两个数字参数,将较小的数字返回.
    '''
    num1 = input('请输入第一个数字:').strip()
    num2 = input('请输入第二个数字:').strip()
    
    
    def func(a, b): return b if a > b else a
    
    
    print(func(num1, num2))
    
    '''
    14. 写函数,接收一个参数(此参数类型必须是可迭代对象),将可迭代对象的每个元素以’_’相连接,形成新的字符串,并返回.
        例如 传入的可迭代对象为[1,'老男孩','武sir']返回的结果为’1_老男孩_武sir’
    '''
    lis = [1, '老男孩', '武sir']
    
    def func(lis):
        s = '_'.join(str(i) for i in lis) 
        return s
    
    print(func(lis))
    
    '''
    15. 写函数,传入n个数,返回字典{‘max’:最大值,’min’:最小值}
        例如:如:min_max(2,5,7,8,4) 返回:{‘max’:8,’min’:2}(此题用到max(),min()内置函数)
    '''
    
    l1 = [2, 5, 7, 8, 4]
    
    def func(*args):
        dic = {}
        dic['max'] = max(args)
        dic['min'] = min(args)
        return dic
    
    
    print(func(*l1))
    
    '''
    16. 写函数,传入一个参数n,返回n的阶乘
        例如:cal(7)  计算7*6*5*4*3*2*1
    '''
    
    def cal(n):
        count = 1
        for i in range(1, n + 1):
            count = i * count
        return count
    
    
    n = int(input('请输入一个数字:'))
    print(cal(n))
    
    '''
    17. 写函数,返回一个扑克牌列表,里面有52项,每一项是一个元组
        例如:[(‘红心’,2),(‘草花’,2), …(‘黑桃’,‘A’)]
    '''
    
    def func():
        l1 = ['黑桃', '红心', '草花', '方片']
        l2 = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A']
        li = []
        for i2 in l2:
            for i1 in l1:
                li.append((i1, i2))
        return li
    
    
    print(func())
    '''
    18. 有如下函数:
    def wrapper():
        def inner():
            print(666)
    wrapper()
    你可以任意添加代码,用两种或以上的方法,执行inner函数.
    '''
    # 方法一:
    def wrapper():
        def inner():
            print(666)
        inner()
    wrapper()
    
    # 方法二:
    def wrapper():
    
        def inner():
            print(666)
        return inner()
    
    
    wrapper()
    
    
    '''
    作业:用函数完成登录注册以及购物车的功能。
        1,启动程序,用户可选择四个选项:登录,注册,购物,退出。
        2,用户注册,用户名不能重复,注册成功之后,用户名密码记录到文件中。
        3,用户登录,用户名密码从文件中读取,进行三次验证,验证不成功则退出整个程序。
        4,用户登录成功之后才能选择购物功能进行购物,购物功能(就是将购物车封装到购物的函数中)。
        5,退出则是退出整个程序。
    
    '''
    
    # 定义商品信息
    shoping = {'1': {'name': '电脑', 'price': 1999},  # 选择商品编号的时候,输入的是字符串,所以此处编号用str型
               '2': {'name': '鼠标', 'price': 10},
               '3': {'name': '键盘', 'price': 20},
               }
    # 定义购物车信息
    my_car = {
        'accounts_money': 0,  # 账户余额
        'shopping_cart': {},  # 购物车内的商品,因为商品有多种,每种商品有价格和名称,所以用dic型
    }
    
    
    # 注册
    def register():
        while 1:
            username = input('请输入用户名:')
            password = input('请输入密码:')
            with open('/Users/chensihan/Documents/shanshan/作业/register_file.txt', encoding='utf-8', mode='r+') as f:
                for content in f:
                    content1 = content.split()
                    if username == content1[0]:
                        print('用户名已存在,请重新输入')
                        break
                else:
                    f.write(username + ' ' + password + '
    ')
                    print('注册成功')
                    break
    
    
    # 登录
    def login():
        global success
        count = 1
        while count <= 3:
            username = input('请输入用户名:')
            password = input('请输入密码:')
            with open('/Users/chensihan/Documents/shanshan/作业/register_file.txt', 'r', encoding='utf-8') as f:
                for content in f:
                    content1 = content.strip().split()
                    if username == content1[0] and password == content1[1]:
                        print('登录成功!')
                        success = 2
                        break
                else:
                    print('用户名或密码错误,请重新输入,还有%s次机会' % (3 - count))
                    count += 1
                    continue
                break
    
    
    # 购物
    def buy():
        # 充值
        while 1:
            money = input('请先充值:').strip()  # 去除输入时的左右空格等
            if money.isdigit():  # 判断输入的金额是否是数字
                my_car['accounts_money'] = int(money)  # 将充值金额传给账户余额
                print('成功充值%s元' % money)
                break
            else:
                print('充值失败,请输入正确的金额')
        
        while 1:
            # 循环打印购物车商品信息,共用户选择添加到购物车
            for i in shoping:
                print(i, shoping[i]['name'], shoping[i]['price'])
            
            num = input('请输入商品序号,将会添加至购物车,退出请输入Q/q,结算请输入n:')
            if num in shoping:  # 判断输入的商品序号是否在商品信息内
                # 记录购物车物品数量
                count = my_car['shopping_cart'].setdefault(num, 0)  # setdefault表示新建一个键值对(x, 0),并将value的值会返给count
                my_car['shopping_cart'][num] = count + 1  # 用户每次输入商品序号,购物车中该商品的数量+1
            
            # 购物车结算
            elif num.lower() == 'n':
                # 先计算出当前购物车的总金额,以便判断结算时是否充足
                total_money = 0  # 初始化购物车的总金额
                for i in my_car['shopping_cart']:
                    # 计算购物车内商品的总金额,每循环一次商品,金额都会在原来的基础上累加
                    total_money += shoping[i]['price'] * my_car['shopping_cart'][i]  # 总金额 = 商品单价*商品数量
                
                # 判断购物车中的金额是否超出当前账户余额
                if total_money > my_car['accounts_money']:  # 如果账户余额>购物车中的总金额
                    for i in my_car['shopping_cart']:  # 判断哪些商品在购物车中
                        # 打印购物车商品信息,序号、商品名称、商品单价、商品数量,供用户删除
                        print(i, shoping[i]['name'], shoping[i]['price'], my_car['shopping_cart'][i])
                    del_num = input('余额不足,请删除购物车任意商品:')
                    
                    # 判断要删除的商品是否在购物车内
                    if del_num in my_car['shopping_cart']:
                        my_car['shopping_cart'][del_num] -= 1  # 购物车内输入的编号对应的商品数量-1
                        
                        # 如果购物车内该商品只剩下一件,则直接删除该商品
                        if my_car['shopping_cart'][del_num] == 0:
                            my_car['shopping_cart'].pop(del_num)
                
                else:  # 如果账户余额<=购物车中的总金额
                    print('购物车商品如下:')
                    # 打印当前购物车剩余商品信息,商品名称、商品单价、商品数量
                    for i in my_car['shopping_cart']:
                        print(shoping[i]['name'], shoping[i]['price'], my_car['shopping_cart'][i])
                    # 购物完成后,计算当前账户余额
                    my_car['accounts_money'] -= total_money
                    print('本次共消费%s元,账户余额%s元' % (total_money, my_car['accounts_money']))
                    break
            elif num.upper() == 'Q':
                print('您已退出购物车')
                break
            else:
                print('输入错误,请重新输入')
    
    
    # 退出程序
    def tui():
        exit("您已退出程序,byebye!!!")
    
    
    # 主体结构
    dic = {
        '1': register,
        '2': login,
        '3': buy,
        '4': tui
    }
    
    
    # 开始启动并选择
    def start():
        while 1:
            print('''
                1.注册
                2.登陆
                3.购物
                4.退出
                ''')
            choice = input('>>>').strip()
            if choice in dic:
                dic[choice]()
            else:
                print('输入错误,请重新选择')
    start()
    day3-用函数实现购物车
  • 相关阅读:
    android Notification 通知栏点击不能跳转(转自:http://www.oschina.net/question/778954_212394)
    Android使用ContentObserver监听数据库变化(转自:http://www.blogjava.net/zhaojianhua/archive/2011/10/27/362204.html)
    cenos 6.4 samba 服务器安装与配置
    centos下nginx+tomcat部署java web全过程(包括在线离线安装Mysql等)
    python读取csv文件
    linux文件实时同步
    Linux 上安装 mysql
    Mysql5.7.20安装文档
    Cassanfra、Hbase和MongoDB的选取
    org.springframework.http.converter.HttpMessageConversionException: T
  • 原文地址:https://www.cnblogs.com/caoyinshan/p/9904652.html
Copyright © 2020-2023  润新知