函数—函数进阶—作业需求

 1 '''
 2 1、编码问题
 3   请说明python2 与python3中的默认编码是什么?
 4       python2:ASCII
 5       python3:UTF—8
 6   为什么会出现中文乱码?你能列举出现乱码的情况有哪几种?
 7       存到硬盘上时是以何种编码存的,再从硬盘上读出来时,就必须以何种编码读,不然就会出现中文乱码。
 8       终端为UTF-8,locale为zh_CN.GBK
 9       终端为UTF-8,locale为zh_CN.UTF-8
10       终端为GBK,locale为zh_CN.GBK
11       终端为GBK,locale为zh_CN.UTF-8
12   如何进行编码转换?
13       UTF-8 --> decode 解码 --> Unicode
14       Unicode --> encode 编码 --> GBK / UTF-8
15   #-*-coding:utf-8-*- 的作用是什么?
16        声明编码为:utf_8
17   解释py2 bytes vs py3 bytes的区别
18        python2   str == bytes
19        python3 中需要通过 unicode
20            string -> encode  -> bytes
21            bytes -> decode  -> string
22 
23 2、文件处理
24    r和rb的区别是什么?
25         r 为 读模式
26         rb 为 二进制读模式
27    解释一下以下三个参数的分别作用,open(f_name,'r',encoding="utf-8")
28         f_name   文件名
29         r      模式
30         encoding  编码方式
31 '''

3、函数基础

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

    1 def sum(x,y):
    2      sum = x + y
    3      print(sum)
    4 sum(2,3)
    5 
    6 lambda x,y : x+y
  • 写函数,用户传入修改的文件名,与要修改的内容,执行函数,完成整个文件的批量修改操作。

     1 def func():
     2      name = input("要修改的文件名:")
     3      content = input("要修改的内容:")
     4      content1 = input("修改后的内容:")
     5      new_name = name+'.new'
     6 
     7      import os         #加载模块
     8      f = open(name,mode = 'r')       #打开要修改的文件
     9      f_new = open(new_name,mode = 'w')      #打开修改后写入的文件
    10 
    11      for i in f:                    #循环文件中每一行的的数据
    12           if content in i:
    13                new_i = i.replace(content,content1)       #将要修改的内容字符串用replace替换
    14           else:
    15                new_i = i
    16           f_new.write(new_i)
    17      f.close()       #关闭要修改的文件
    18      f_new.close()   #关闭修改后写入的文件
    19      os.rename(new_name,name)      #将写入修改后内容的文件改名为修改的文件名,这样就相当于修改了原来的文件
    20 func()
  • 写函数,检查用户传入的对象(字符串、列表、元组)的每一个元素是否含有空内容。

    1 def func(*file):
    2      n = 0
    3      for i in file:
    4           if i == ' ':
    5                n += 1
    6      print("含有%s个空行"%n)
    7 func(*[1,' ',2])
  • 写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。

    dic = {"k1": "v1v1", "k2": [11,22,33,44]}
    PS:字典中的value只能是字符串或列表
    1 dic = {"k1": "v1v1", "k2": [11,22,33,44]}
    2 def func(dic):
    3      for i in dic:
    4           if len(dic[i]) > 2:
    5                dic[i] = dic[i][:2]
    6      return dic
    7 f = func(dic)
    8 print(f)
  • 解释闭包的概念。

     1 闭包:即函数定义和函数表达式位于另一个函数的函数体内(嵌套函数)。
     2 这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数。
     3 当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。
     4 也就是说,内部函数会在外部函数返回后被执行。而当这个内部函数执行时,它仍然必需访问其外部函数的局部变量、参数以及其他内部函数。
     5 这些局部变量、参数和函数声明(最初时)的值是外部函数返回时的值,但也会受到内部函数的影响
     6 
     7 例:
     8 def func():
     9     n = 10
    10 
    11     def func2():
    12         print("func2:",n)
    13     return func2    #返回func2的内存地址
    14 
    15 f = func()
    16 print(f)         #结果为:<function func.<locals>.func2 at 0x000002F1B9F59730>
    17 f()              #结果为:func2: 10
    18 
    19 #按常理来讲,执行完func()函数后,func2()已经释放了,但是它返回了   func2: 10
    20 #在外部拿到了内部的函数,并且还可以使用内部函数的作用域里面的值
    21 
    22 #闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域

     

4、函数进阶

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

     1 def func():
     2      num = []
     3      for i in range(2,11):
     4           num.append(i)
     5      num.extend(['J','Q','K','A'])
     6      data = ['红心','草花','方块','黑桃']
     7      num1 = []
     8      for i in num:
     9           for j in data:
    10                num1.append((j,i))
    11      return num1
    12 f = func()
    13 print(f)
  • 写函数,传入n个数,返回字典{‘max’:最大值,’min’:最小值}。例如:min_max(2,5,7,8,4),返回:{‘max’:8,’min’:2}

     1 def min_max(*args):
     2      max = args[0]
     3      min = args[0]
     4      for i in args:
     5           if i > max:
     6                max = i
     7           elif i < min:
     8                min = i
     9      return {'max': max , 'min': min}
    10 print(min_max(3,2,6,8,15,17,-9,38,5))
  • 写函数,专门计算图形的面积

     1 # 其中嵌套函数,计算圆的面积,正方形的面积和长方形的面积
     2 # 调用函数area(‘圆形’,圆半径) 返回圆的面积
     3 # 调用函数area(‘正方形’,边长) 返回正方形的面积
     4 # 调用函数area(‘长方形’,长,宽) 返回长方形的面积
     5 # def area():
     6 #    def 计算长方形面积():
     7 #          pass
     8 #
     9 #    def 计算正方形面积():
    10 #          pass
    11 #
    12 #    def 计算圆形面积():
    13 #         pass
    14 def area():
    15      def rectangle(x,y):
    16           print(x*y)
    17      def square(s):
    18           print(s*s)
    19      def circle(r):
    20           print(3.14*r*r)
    21 
    22      name = input('请输入图形名称:')
    23      if name == '长方形':
    24           x = int(input('请输入长方形的长:'))
    25           y = int(input('请输入长方形的宽:'))
    26           rectangle(x,y)
    27      elif name == '正方形':
    28           s = int(input('请输入正方形的边长:'))
    29           square(s)
    30      elif name == '圆形':
    31           r = int(input('请输入圆的半径:'))
    32           circle(r)
    33 print(area())
  • 写函数,传入一个参数n,返回n的阶乘。

    1 def func2(n):
    2      res = 1
    3      for i in range(n,0,-1):
    4           res = res * i
    5      return  res
    6 print(func2(5))

     

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

     1 user_status = False  # 用户登录了,就把这个改成True
     2 def login(auth_type):
     3      def iner():
     4           global user_status
     5           if user_status == False:
     6                username = input("user:")
     7                password = input("password:")
     8 
     9                f = open('data.txt','r')
    10                da = eval(f.read())
    11                if username in da:
    12                     if password == da[username]:
    13                          user_status = True
    14           if user_status == True:
    15                auth_type()
    16      return iner
    17 
    18 @login
    19 def func():
    20     print('---func---')
    21 @login
    22 def func1():
    23     print('----func1----')
    24 @login
    25 def func2():
    26     print('-----func2----')
    27 
    28 @login
    29 def func3():
    30      print('-----func3----')
    31 
    32 func()
    33 func3()

     

5、生成器和迭代器

  • 生成器和迭代器的区别?

    1     对于list、string、tuple、dict等这些容器对象,使用for循环遍历是很方便的。在后台for语句对容器对象调用iter()函数。iter()是python内置函数。 
    2     iter()函数会返回一个定义了next()方法的迭代器对象,它在容器中逐个访问容器内的元素。next()也是python内置函数。在没有后续元素时,next()会抛出一个StopIteration异常,通知for语句循环结束。
    3     迭代器是用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用next()函数的时候,迭代器会向我们返回它所记录位置的下一个位置的数据。实际上,在使用next()函数的时候,调用的就是迭代器对象的_next_方法(Python3中是对象的_next_方法,    Python2中是对象的next()方法)。所以,我们要想构造一个迭代器,就要实现它的_next_方法。但这还不够,python要求迭代器本身也是可迭代的,所以我们还要为迭代器实现_iter_方法,而_iter_方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的_iter_方法返回自身self即可。
    4 
    5 
    6    生成器是一种特殊的迭代器,生成器自动实现了“迭代器协议”(即__iter__和next方法),不需要再手动实现两方法。
    7    生成器在迭代的过程中可以改变当前迭代值,而修改普通迭代器的当前迭代值往往会发生异常,影响程序的执行。

     

  • 生成器有几种方式获取value?

    1 三种方式获取:
    2    while        会报错
    3    for  循环
    4    next 获取

     

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

         根据指令向屏幕输出日志

        根据指令向文件输出日志

        根据指令同时向文件&屏幕输出日志

        以上日志格式如下

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]是指自日志方法第几次调用,每调用一次输出一条日志
 1 def logger(filename,channel='file'):
 2 """
 3 日志方法
 4 :param filename: log filename
 5 :param channel: 输出的目的地,屏幕(terminal),文件(file),屏幕+文件(both)
 6 :return:
 7 """
 8 ...your code...
 9 
10 #调用
11 log_obj = logger(filename="web.log",channel='both')
12 log_obj.__next__()
13 log_obj.send('user alex login success')

 

6、内置函数

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

     1 #map  它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。map()函数在不改变原有的lisy,而是返回一个新的list
     2 print(map(lambda x: x*x , [1,2,3,4,5]))         #结果为:<map object at 0x0000022DB38384A8>
     3 print(list(map(lambda x: x*x , [1,2,3,4,5])))   #结果为:[1, 4, 9, 16, 25]
     4 
     5 #解答:
     6 name=['alex','wupeiqi','yuanhao','nezha']
     7 def func(x):
     8     return x + '_sb'
     9 res = map(func,name)
    10 print(list(res))

     

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

     1 #filter
     2 print(filter(lambda x: x>3 , [1,2,3,4,5]))         #结果为:<filter object at 0x000002B9B1CC84E0>
     3 print(list(filter(lambda x: x>3 , [1,2,3,4,5])))   #结果为:[4, 5]
     4 
     5 #解答
     6 num = [1,3,5,6,7,8]
     7 def func(x):
     8     if x%2 == 0:
     9         return x
    10 res = filter(func,num)
    11 print(list(res))

     

  • 如下,每个小字典的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}
    ]
    1 #计算购买每支股票的总价
    2 for i in portfolio:
    3     print(i['name'],i['shares']*i['price'])
    4 #或者
    5 print([(item['name'],item['shares']*item['price']) for item in portfolio])
     1 #用filter过滤出,单价大于100的股票有哪些
     2 portfolio = [
     3     {'name': 'IBM', 'shares': 100, 'price': 91.1},
     4     {'name': 'AAPL', 'shares': 50, 'price': 543.22},
     5     {'name': 'FB', 'shares': 200, 'price': 21.09},
     6     {'name': 'HPQ', 'shares': 35, 'price': 31.75},
     7     {'name': 'YHOO', 'shares': 45, 'price': 16.35},
     8     {'name': 'ACME', 'shares': 75, 'price': 115.65}
     9 ]
    10 print(list(filter(lambda i:i['price'] >100,portfolio)))

     

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

 1 模式       含义
 2 r          文本只读模式
 3 rb         二进制模式,这种方法是用来传输或存储,不给人看的
 4 r+         读写模式,只要有r,那么文件必须存在
 5 rb+        二进制读写模式
 6 w          只写模式,不能读,用w模式打开一个已经存在的文件,如果有内容会清空,重新写
 7 wb         以二进制方式打开,只能写文件,如果不存在,则创建
 8 w+         读写模式,先读后写,只要有w,会清空原来的文件内容
 9 wb+        二进制读写模式
10 a          追加模式,也能写,在文件的末尾添加内容
11 ab         二进制追加模式
12 a+         追加模式,如果文件不存在,则创建文件,如果存在,则在末尾追加
13 ab+        追读写二进制模式,从文件顶部读取文件,从文件底部添加内容,不存在则创建

 

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

 1 # startswith      a.startsWith(b)       判断字符串a 是不是以字符串b开头.
 2 # append       在被选元素的结尾(仍然在内部)插入指定内容.
 3 # capitalize      返回一个字符串,首字母为大写,其他字母为小写
 4 li = ['alex', 'egon', 'smih', 'pizza', 'alen']
 5 #方法一:
 6 new_li = []
 7 for i in li:
 8     if i.startswith('a'):
 9         new_li.append(i.capitalize())
10     else:
11         new_li.append(i)
12 print(new_li)
13 
14 #方法二:
15 for i in range(len(li)):
16     if li[i][0] == 'a':
17         li[i] = li[i].capitalize()
18     else:
19         continue
20 print(li)
21 
22 #方法三:
23 print([item.capitalize() if item.startswith('a') else item for item in li])

 

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

 1 num = 20
 2 def show_num(x=num):
 3     print(x)
 4 
 5 show_num()      #结果为:20
 6 
 7 num = 30
 8 show_num()      #结果为:20
 9 
10 # 如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象,相当于通过“传值’来传递对象
11 #如果想改变这些变量的值,可以将这些变量申明为全局变量


10、有列表 li = ['alex', 'egon', 'smith', 'pizza', 'alen'], 请以列表中每个元素的第二个字母倒序排序

#sorted((1,4,8,9,3,6), reverse=True)     #结果为: [9, 8, 6, 4, 3, 1]
li = ['alex', 'egon', 'smith', 'pizza', 'alen']
print(sorted(li,key=lambda x : x[1],reverse = True))

 

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

 1 '''
 2    昔人已乘黄鹤去,此地空余黄鹤楼。
 3 
 4    黄鹤一去不复返,白云千载空悠悠。
 5 
 6    晴川历历汉阳树,芳草萋萋鹦鹉洲。
 7 
 8    日暮乡关何处是?烟波江上使人愁。
 9 '''
10 import os
11 f1=open('poetry.txt', 'r',encoding='utf-8')
12 
13 str='晴川历历汉阳树,芳草萋萋鹦鹉洲。'
14 with open('poetry1.txt', 'w', encoding='utf-8') as f2:
15       ff1='poetry.txt'
16       ff2='poetry1.txt'
17       for line in f1:
18           if str in line:
19               line=''
20               f2.write(line)
21 
22           else:
23               f2.write(line)
24 f1.close()
25 f2.close()
26 os.replace(ff2,ff1)

 

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

  pizza
  alex
  egon
1 with open('username.txt','r+',encoding='utf-8')as f:
2     s = 'alex'
3     i = f.read()
4     print(i)
5     if s in i:
6         print('该用户已存在')
7     else:
8         f.write('\nalex')

 

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

 1 f_name = r'user_info.txt'
 2 f_new_name = '%s.new'%f_name
 3 del_id = '100001'
 4 f_new = open(f_new_name, 'w', encoding='utf-8')
 5 with open(f_name, 'r', encoding='utf-8') as f:
 6     for line in f:
 7         if del_id in line:
 8             pass
 9         else:
10             f_new.write(line)
11 f_new.close()
12 os.replace(f_new_name,f_name)

 

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

 1 f_name = r'user_info.txt'
 2 f_new_name = '%s.new'%f_name
 3 update_id = '100002'
 4 update_name = 'alex li'
 5 f_new = open(f_new_name, 'w', encoding='utf-8')
 6 with open(f_name, 'r', encoding='utf-8') as f:
 7     for line in f:
 8         if update_id in line:
 9             line = ','.join([update_name, update_id])
10             f_new.write(line+'\n')
11         else:
12             f_new.write(line)
13 f_new.close()
14 os.replace(f_new_name,f_name)