zoukankan      html  css  js  c++  java
  • python作业03-文件操作&函数

    一、文件处理相关

    1、编码问题   

      (1)请说明python2 与python3中的默认编码是什么?
    答:Python2默认的字符编码是ASCII,默认的文件编码也是ASCII ;python3默认的字符编码是unicode,默认的文件编码是utf-8。

        (2)为什么会出现中文乱码?你能列举出现乱码的情况有哪几种?
    答:无论以什么编码在内存里显示字符,在硬盘上存储都是二进制。存到硬盘是以何种编码,再从硬盘读取出来,就必须是何种编码,不然就会出现乱码。解释器默认编码、Terminal编码、文件编码、操作系统语言设置。

        (3)如何进行编码转换?
    答:对文件先decode为unicode,再encode为需要转换的编码。

        (4)#-*-coding:utf-8-*- 的作用是什么?
    答:告诉解释器这个文件的编码格式是utf-8

        (5)解释py2 bytes vs py3 bytes的区别
    答:python3把字符串的编码改成了unicode, 还把str和bytes做了明确区分, str就是unicode格式的字符,bytes是单纯二进制。
        在python2里,将string处理为原生的bytes类型。

    2、文件处理
        (1)r和rb的区别是什么?
    答:r是文本只读模式
        rb:二进制只读模式,无法指定encoding,因为在该模式下数据读到内存里直接是bytes格式,如要查看内容还需手动decode
        (2)解释一下以下三个参数的分别作用
         open(f_name,'r',encoding="utf-8")
    答:f_name将打开的当前目录文件名,r:文本只读模式,encoding="utf-8":指定打开文件为utf-8编码模式。

    二、函数基础

    1、写函数,计算传入数字参数的和。(动态传参)

    def func(*args):
        list1 = []
        sum_data = 0
        for i in args:
            list1.append(i)
            sum_data += i
        print(list1)
        print(sum_data)
    
    func(313, 213, 12, 1234, 453, 56)

    2、写函数,用户传入修改的文件名,与要修改的内容,执行函数,完成整个文件的批量修改操作

    def file_modify(filename, old, new):
        import os
        f = open(filename, mode='r+', encoding='utf-8')
        new_f = open(filename+"_bak", mode='w', encoding='utf-8')
        for line in f:
            if old in line:
                line = line.replace(old,new)
            new_f.write(line)
        os.remove(filename)
        os.rename(filename+"_bak",filename)
    
    file_modify('aaaa.txt', 'ddd', 'goodman')

    3、写函数,检查用户传入的对象(字符串、列表、元组)的每一个元素是否含有空内容。

    def func(args):
        n = 0
        for i in args:
            if i == "":
                n += 1
        print("有%s个空内容"%n)
    
    func((1, '', 2, 44, '', 12))

    4、写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。

      dic = {"k1": "v1v1", "k2": [11,22,33,44]}
          PS:字典中的value只能是字符串或列表

    def func(args_dic):
        for i in args_dic:
            if len(args_dic[i]) > 2:
                item = args_dic[i][0:2]  # 前两项
                args_dic[i] = item
        print(args_dic)
    
    dic = {"k1": "v1v1", "k2": [11,22,33,44]}
    func(dic)
    # {'k1': 'v1', 'k2': [11, 22]}

    5、解释闭包的概念
    答:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。

    三、函数进阶

    1、写函数,返回一个扑克牌列表,里面有52项,每一项是一个元组
        例如:[(‘红心’,2),(‘草花’,2), …(‘黑桃A’)]

    def poker():
        a = ['红心', '草花', '方片', '黑桃']
        b = [2, 3, 4, 5, 6, 7, 8, 9, 10]
        c = ['J', 'Q', 'K', 'A']
        li = []
        for i in b:
            for j in a:
                item = (j,i)
                li.append(item)
        for m in c:
            for n in a:
                item2 = (n+m)
                li.append(item2)
        print(li)
        print(len(li))
    
    poker()

    2、写函数,传入n个数,返回字典{‘max’:最大值,’min’:最小值}
        例如:min_max(2,5,7,8,4)
        返回:{‘max’:8,’min’:2}

    def min_max(*args):  # dict形式
        li = []
        for i in args:
            li.append(i)
        li.sort()
        dic = {'max':li[-1], 'min':li[0]}
        print(dic)
    
    min_max(2,5,7,8,4)
    # 输出:{'max': 8, 'min': 2}

    3、写函数,专门计算图形的面积
        其中嵌套函数,计算圆的面积,正方形的面积和长方形的面积
        调用函数area(‘圆形’,圆半径) 返回圆的面积
        调用函数area(‘正方形’,边长) 返回正方形的面积
        调用函数area(‘长方形’,长,宽) 返回长方形的面积

    def area(type, *args):
    
        def rectangle(length, wide):
            return "长方形面积", length*wide
    
        def square(length):
            return "正方形面积", length**2
    
        def circlar(radius):
            import math
            return "圆形面积", math.pi*(radius**2)
        if type in locals():
            return eval(type)(*args)
    print(area('rectangle', 133, 4))
    print(area('circlar', 20))
    print(area('square', 10))

    4、写函数,传入一个参数n,返回n的阶乘
        例如:cal(7)
        计算7*6*5*4*3*2*1

    def cal(n):
        item = 1
        if int(n) == n:
            li = range(n+1)
            for i in li:
                if i == 0:
                    pass
                else:
                    item = item*i
            print(item)
        else:
            return "%s不是整数"%n
    
    cal(3)
    
    # 法二:
    def cal(n):
        result=1
        for i in range(n, 0, -1): # 倒序
            result=result*i
        return result
    
    print(cal(7))

    5、编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码

    user_db = {
        'hqs':'123',
        'susiff':'123',
        'guangfa':'123'
    }
    
    with open('db.txt', 'w', encoding='utf-8') as f:
        f.write(str(user_db))
    login_db = {'user': None, 'status': False}
    db_path = r'db.txt'
    
    def login(func):
        def inner(*args,**kwargs):
            if login_db['user'] and login_db['status']:
                res = func(*args, **kwargs)
                return res
            user = input('input user:')
            passwd = input('input passwd:')
            with open(db_path, 'r', encoding='utf-8') as f:
                user_db2 = eval(f.read())
            if user in user_db2 and passwd == user_db2[user]:
                print('login ok')
                login_db['user'] = user
                login_db['status'] = True
                res = func(*args, **kwargs)
                return res
            else:
                print('login error')
        return inner  # 加括号执行,不加括号返回内存地址
    
    @login
    def home():
        print("首页".center(40,'-'))
    
    @login
    def america(name):
        print("欧美专区".center(40,'-'))
    
    
    home()
    america('hqs')

    四、生成器和迭代器

    1、生成器和迭代器的区别?
    可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator).
    在Python中,可以在循环过程中不断推算后续元素,这种一边循环一边计算的机制,称为生成器(generator)。
    生成器是迭代器的一种:
        1.生成器都是迭代器对象,但listdictstr虽然是可迭代对象,但不是迭代器。
        2.把listdictstr等可迭代对象变成迭代器可以使用iter()函数

    2、生成器有几种方式获取value?
      1.next():唤醒生成器并继续执行
      2.send():唤醒生成器并继续执行;发送一个信息到生成器内部。     3.for循环

    3、通过生成器写一个日志调用方法, 支持以下功能

    • 根据指令向屏幕输出日志
    • 根据指令向文件输出日志
    • 根据指令同时向文件&屏幕输出日志
    • 以上日志格式如下
    2017-10-19 22:07:38 [1] test log db backup 3
    2017-10-19 22:07:40 [2]    user alex login success 
    #注意:其中[1],[2]是指自日志方法第几次调用,每调用一次输出一条日志
    •  代码结构如下:
    def logger(filename,channel='file'):
        """
        日志方法
        :param filename: log filename
        :param channel: 输出的目的地,屏幕(terminal),文件(file),屏幕+文件(both)
        :return:
        """
        ...your code...
    
     #调用
     log_obj = logger(filename="web.log",channel='both')
     log_obj.__next__()
     log_obj.send('user alex login success')

     解答如下:

    def logger(filename, channel):
        """
        日志方法
        :param filename: log filename
        :param channel: 输出的目的地,屏幕(terminal),文件(file),屏幕+文件(both)
        :return:
        """
        import time
        a = time.localtime()
        log_time = time.strftime('%Y-%m-%d %H:%M:%S', a)
        count = 0
        while count < 10:
            count += 1
            sign = yield count
            log_info = log_time + ' [' + str(count) + '] ' + sign
            if channel == 'file':
                f = open(filename, mode='a+', encoding='utf-8')
                f.write('
    '+log_info)
                f.close()
            elif channel == 'terminal':
                print(log_info)
            elif channel == 'both':
                f = open(filename, mode='a+', encoding='utf-8')
                f.write('
    ' + log_info)
                f.close()
                print(log_info)
            else:
                print('请输入正确的模式!')
    
    
    log_obj = logger(filename="web.log", channel='both')
    log_obj.__next__()
    log_obj.send('user alex login success')
    log_obj.send('user hqs login success')

    五、内置函数

    1、用map来处理字符串列表,把列表中所有人都变成sb,比方alex_sb。

    name = ['alex','wupeiqi','yuanhao','nezha']
    
    print(list(map(lambda x: x+'_sb', name)))
    """
    ['alex_sb', 'wupeiqi_sb', 'yuanhao_sb', 'nezha_sb']
    """

    2、用filter函数处理数字列表,将列表中所有的偶数筛选出来。

    num = [1, 3, 5, 6, 7, 8]
    
    print(list(filter(lambda x: x % 2 == 0, num)))
    """
    [6, 8]
    """

    3、如下,每个小字典的name对应股票名字,shares对应多少股,price对应股票的价格。

    portfolio = [
        {'name': 'IBM', 'shares': 100, 'price': 91.1},
        {'name': 'AAPL', 'shares': 50, 'price': 543.22},
        {'name': 'FB', 'shares': 200, 'price': 21.09},
        {'name': 'HPQ', 'shares': 35, 'price': 31.75},
        {'name': 'YHOO', 'shares': 45, 'price': 16.35},
        {'name': 'ACME', 'shares': 75, 'price': 115.65}
    ]

      计算购买每支股票的总价;用filter过滤出,单价大于100的股票有哪些?

    portfolio = [
        {'name': 'IBM', 'shares': 100, 'price': 91.1},
        {'name': 'AAPL', 'shares': 50, 'price': 543.22},
        {'name': 'FB', 'shares': 200, 'price': 21.09},
        {'name': 'HPQ', 'shares': 35, 'price': 31.75},
        {'name': 'YHOO', 'shares': 45, 'price': 16.35},
        {'name': 'ACME', 'shares': 75, 'price': 115.65}
    ]
    
    
    def sum_shares(dic):
        name = dic['name']
        shares = dic['shares']
        price = dic['price']
        sum_price = "%.2f" % (shares * price)
        new_dic = {'name':name, 'sum_price':sum_price}
        return new_dic
    
    
    print(list(map(sum_shares, portfolio)))  # 每支总价
    """
    [
      {'name': 'IBM', 'sum_price': 9110.00},
      {'name': 'AAPL', 'sum_price': 27161.00}, 
      {'name': 'FB', 'sum_price': 4218.00},
      {'name': 'HPQ', 'sum_price': 1111.25}, 
      {'name': 'YHOO', 'sum_price': 735.75}, 
      {'name': 'ACME', 'sum_price': 8673.75}]
    """
    
    print(list(filter(lambda x: x['shares'] > 100, portfolio)))
    """
    [{'name': 'FB', 'shares': 200, 'price': 21.09}]
    """

    六、进阶练习

    1、请分别介绍文件操作中不同的打开方式之间的区别:

      r:文本只读模式,以什么模式存文件,就以什么编码打开文件

      rb:二进制只读模式,该模式下数据读取到内存里直接就是bytes格式,无法指定encoding

      r+:读写文件模式,可读可写可追加

      rb+:二进制读写模式,在内存中读取写入的均为bytes格式

      w:只写模式,不可读,不存在则创建,存在则清空内容

      wb:二进制写模式

      w+:写读模式,以创建的模式打开(将原文件覆盖),可以读取写入的内容

      wb+:二进制写读模式

      a:追加模式,可读,不存在则创建,存在则只追加内容

      ab:二进制追加模式

      a+:同a

      ab+:同ab

    2、有列表 li = ['alex', 'egon', 'smith', 'pizza', 'alen'], 请将以字母“a”开头的元素的首字母改为大写字母;

    li = ['alex', 'egon', 'smith', 'pizza', 'alen']
    
    def str_upper(x):
        if x[0] == 'a':
            x = 'A' + x[1:]
        else:
            pass
        return x
    
    print(list(map(str_upper, li)))
    """
    ['Alex', 'egon', 'smith', 'pizza', 'Alen']
    """

    3、有如下程序, 请给出两次调用show_num函数的执行结果,并说明为什么:

    num = 20
    
    def show_num(x=num):
        print(x)
    
    show_num()
    
    num = 30
    
    show_num()
    """
    20
    30
    """

    答:函数参数x是取得num的值,num的值属于全局变量,第一次调用函数的时候,全局变量num=20,第二次调用时,全局变量num发生了修改num=30

    4、有列表 li = ['alex', 'egon', 'smith', 'pizza', 'alen'], 请以列表中每个元素的第二个字母倒序排序;(后面调整解法)

    li = ['alex', 'egon', 'smith', 'pizza', 'alen']
    
    
    def str_sort(li):
    
        def cut_li(x):
            new_x = x[1:]
            return new_x
        new_li = list(map(cut_li, li))
        new_li.sort()
        new_li.reverse()
        final_li = []
        for i in new_li:
            for j in li:
                if i == j[1:]:
                    final_li.append(j)
    
        print(final_li)
    
    
    str_sort(li)

    运用内置函数sorted改写该题:

    # 方法二:内置函数sorted()
    li = ['alex', 'egon', 'smith', 'pizza', 'alen']
    new_li = sorted(li, key=lambda x: x[1], reverse=True)
    print(new_li)
    """
    ['smith', 'alex', 'alen', 'pizza', 'egon']
    """

    5、有名为poetry.txt的文件,其内容如下,请删除第三行;

       昔人已乘黄鹤去,此地空余黄鹤楼。
    
       黄鹤一去不复返,白云千载空悠悠。
    
       晴川历历汉阳树,芳草萋萋鹦鹉洲。
    
       日暮乡关何处是?烟波江上使人愁。
    import os
    filename = 'poetry.txt'
    file = open(filename, 'r', encoding='utf-8')
    new_poetry = []
    for line in file.readlines():
        if line.strip() == '':
            pass
        else:
            new_poetry.append(line.strip())
    del new_poetry[2]
    f = open('%s.new' % filename, 'w')
    for i in new_poetry:
        f.write(i+'
    
    ')
    os.rename('%s.new' % filename, filename)

    6、有名为username.txt的文件,其内容格式如下,写一个程序,判断该文件中是否存在"alex", 如果没有,则将字符串"alex"添加到该文件末尾,否则提示用户该用户已存在;

      pizza
      alex
      egon
    filename = 'username.txt'
    with open(filename, 'r+', encoding='utf-8') as f:
        name = 'alexx'
        i = f.read()
        print(i)
        if name in i:
            print('%s already in this %s' % (name, filename))
        else:
            f.write('
    '+name)

    7、有名为user_info.txt的文件,其内容格式如下,写一个程序,删除id为100003的行;

      pizza,100001
      alex, 100002
      egon, 100003
    import os
    filename = 'user_info.txt'
    with open(filename, 'r+', encoding='utf-8') as f:
        f_new = open('%s_new' % filename, 'w+', encoding='utf-8')
        for i in f:
            if '100003' in i:
                pass
            else:
                f_new.write(i)
    # os.rename('%s_new' % filename, filename)  # 两种都有效果
    os.replace('%s_new' % filename, filename)

    8、有名为user_info.txt的文件,其内容格式如下,写一个程序,将id为100002的用户修改为alex li

      pizza,100001
      alex, 100002
      egon, 100003
    import os
    filename = 'user_info.txt'
    with open(filename,'r+', encoding='utf-8') as f:
        f_new = open('%s_new' % filename, 'w+')
        for i in f:
            if '100002' in i:
                line = i.split(',')
                line[0] = 'alex li'
                i = line[0] +', '+ line[1]
                f_new.write(i)
            else:
                f_new.write(i)
    os.rename('%s_new' % filename, filename)

    9、写一个计算每个程序执行时间的装饰器;

    import time
    def timmer(func):
    
        def inner():
            start_time = time.time()
            func()
            wait_time = time.time() - start_time
            print("%s 运行时间:" % func.__name__, '%.2f' % wait_time)
        return inner
    
    
    a = time.localtime()
    
    @timmer
    def log_1():
        print('%s-%s-%s'%(a.tm_year, a.tm_mon, a.tm_mday))
    @timmer
    def log_2():
        time.sleep(2)
        print('%s-%s-%s' % (a.tm_year, a.tm_mon, a.tm_mday))
    @timmer
    def log_3():
        time.sleep(4)
        print('%s-%s-%s' % (a.tm_year, a.tm_mon, a.tm_mday))
    log_1()
    log_2()
    log_3()

    10、lambda是什么?请说说你曾在什么场景下使用lambda?

    答案:lambda函数就是可以接受任意多个参数(包括可选参数)并且返回单个表达式值得函数

      优势:1.lambda函数比较轻便,即用即仍,适合完成只在一处使用的简单功能。

         2.匿名函数,一般用来给filter,map这样的函数式编程服务

         3.作为回调函数,传递给某些应用,比如消息处理。

    11、题目:写一个摇骰子游戏,要求用户压大小,赔率一赔一。

      要求:三个骰子,摇大小,每次打印摇骰子数。

    import random
    def dice(status):
        a = random.randint(1, 6)  # 返回1-6之间随机数,包括6
        b = random.randint(1, 6)
        c = random.randint(1, 6)
        print(a, b, c)
        result = a + b + c
        if result > 10:
            print('结果是大!')
            if status == '':
                print('你赢了!!')
            if status == '':
                print('你输了!!')
        else:
            print('结果是小!')
            if status == '':
                print('你赢了!!')
            if status == '':
                print('你输了!!')
    
    dice('')
  • 相关阅读:
    洛谷 4035 [JSOI2008]球形空间产生器
    洛谷 2216 [HAOI2007]理想的正方形
    洛谷2704 [NOI2001]炮兵阵地
    洛谷2783 有机化学之神偶尔会做作弊
    洛谷 2233 [HNOI2002]公交车路线
    洛谷2300 合并神犇
    洛谷 1641 [SCOI2010]生成字符串
    Vue history模式支持ie9
    VUE实现登录然后跳转到原来的页面
    vue history模式 apache配置
  • 原文地址:https://www.cnblogs.com/xiugeng/p/8504327.html
Copyright © 2011-2022 走看看