函数编程
1. 编码问题
i.请说明python2与python3中的默认编码是什么?
python2 ASCII 码 python3 字符串为unicode,文件默认编码为utf-8
ii.为什么会出现中文乱码?你能列举出现乱码的情况有哪几种?
读取使用的编码和存储时使用的编码不一致造成的。
存储的时候是GBK,打开的时候是使用UTF-8编码,就会出现乱码
iii.如何进行编码转换?
h = "你好" print(h) print(type(h)) h1 = h.encode(encoding="utf-8") #将字符串编码成utf-8的bytes print(h1) print(type(h1)) h2 = h1.decode(encoding="utf-8").encode(encoding="gbk") print(h2) print(type(h2)) h3 = h2.decode(encoding="gbk") #将gbk编码的bytes解码成字符串(unicode) print(h3) print(type(h3)) 你好 <class 'str'> b'\xe4\xbd\xa0\xe5\xa5\xbd' <class 'bytes'> b'\xc4\xe3\xba\xc3' <class 'bytes'> 你好 <class 'str'>
iv. #-*-coding:utf-8-*- 的作用是什么?
使用utf-8编码。
v. 解释py2 bytes vs py3 bytes的区别:
py2的 bytes和str 是一样的
py3的bytes就是二进制字节
2. 文件处理
i. r 和 rb 的区别是什么?
r 以只读的模式打开文件
rb 以只读的二进制模式打开文件
ii. 解释一下以下三个参数的分别作用
open(f_name,'r',encoding="utf-8")
f_name 是文件名,r 为读的模式, encoding="utf-8" 为打开文件编码
函数基础:
1. 写函数,计算传入数字参数的和。(动态传参)
def num_sum(*args): total_sum = 0 for i in args: total_sum += i print(total_sum) num_sum(2,3,4,-1,12)
2. 写函数,用户传入修改的文件名,与要修改的内容,执行函数,完成整个文件的批量修改操作
import os def updata(file,old_contents,new_contents): with open(file,"r",encoding="utf-8") as f ,open("tmp","w",encoding="utf-8") as f1: for line in f: line = line.replace(old_contents,new_contents) f1.write(line) os.remove(file) os.rename("tmp",file) updata("file.txt","hello","hi")
3. 写函数,检查用户传入的对象(字符串、列表、元组)的每一个元素是否含有空内容。
def isnull(arg): for i in arg: if str(i).isspace(): print("有空白字符,空格 或 制表符 或 换行") isnull(("hh","gg"," ","dd"))
4. 写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
def my_dic(*args,**kwargs): for i in kwargs: if len(kwargs[i]) > 2: print(len(kwargs[i])) kwargs[i] = kwargs[i][:2] return kwargs dic = {"k1": "v1v1", "k2": [11,22,33,44]} print(my_dic(**dic))
5. 解释闭包的概念。
在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包,就是当某个函数被当成对象返回时,夹带了外部变量,就形成了一个闭包。
函数进阶:
1. 写函数,返回一个扑克牌列表,里面有52项,每一项是一个元组 例如:[(‘红心’,2),(‘草花’,2), …(‘黑桃A’)]
def poker(): type_list = ("黑桃","红桃","方块","梅花") num_list = (1,2,3,4,5,6,7,8,9,10,"J","Q","K") poker_list = [] for i in type_list: for j in num_list: poker_list.append((i,j)) print(poker_list)
poker()
2. 写函数,传入n个数,返回字典{‘max’:最大值,’min’:最小值} 例如:min_max(2,5,7,8,4) 返回:{‘max’:8,’min’:2}
def min_max(*args): max = args[0] min = args[0] for i in args: if i >max: max = i if i< min: min = i return {"max":max, "min":min} print(min_max(100,-6,2,3,6,98))
3. 写函数,专门计算图形的面积 其中嵌套函数,计算圆的面积,正方形的面积和长方形的面积 调用函数area(‘圆形’,圆半径) 返回圆的面积 调用函数area(‘正方形’,边长) 返回正方形的面积 调用函数area(‘长方形’,长,宽) 返回长方形的面积 def area(): def 计算长方形面积(): pass def 计算正方形面积(): pass def 计算圆形面积(): pass
def area(shape,*args): def rectangular(*args): area_total = args[0]*args[1] print(area_total) def square(*args): area_total = args[0] * args[0] print(area_total) def circular(*args): area_total = 3.14* args[0] * args[0] print(area_total) if shape == "长方形": return rectangular(*args) elif shape == "正方形": return square(*args) elif shape == "圆形": return circular(*args) area("圆形",2)
4. 写函数,传入一个参数n,返回n的阶乘 例如:cal(7) 计算7*6*5*4*3*2*1
def cal(n): total = 1 for i in range(1,n+1): total *= i print(total) cal(7)
5. 编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
import json logged = False global_user = "" def auth(fun): def inner(*args,**kwargs): global logged if logged == False: user = { "zhangsan": ["zhangsan666",3,False], "lisi": ["lisi666",0,True], "wangwu": ["wangwu666",0,True] } #用户名:[密码,密码输错次数,False锁定用户] while True: name = input("请输入你的姓名:").strip() try: with open("lockedname.txt","r+",encoding="utf-8") as f: user = json.load(f) #若是有lockedname.txt文件,则user重新赋值 with open("expenses_record.txt", "r+", encoding="utf-8") as f2: record_info = json.load(f2) # 若是有lockedname.txt文件,则user重新赋值 except Exception as err: pass if name not in user: print("用户名不存在,请重新输入") continue elif user[name][2] == False: print("用户已经被锁定,请联系管理员") continue elif record_info[name]["frozen"] == True: print("账号已经被冻结,请联系管理员") continue elif name in user: passwd = input("请输入你的密码:").strip() if passwd == user[name][0]: # 判断用户名密码 print("欢迎 %s 同学"%(name)) user[name][1] = 0 with open("lockedname.txt", "w", encoding="utf-8") as f: json.dump(user, f) logged = True global global_user global_user = name result = fun(*args,**kwargs) return (0, name) else: user[name][1] += 1 # 同一个用户名输错密码加一 print("密码错误") if user[name][1] >= 3: print("用户账号已被锁定") user[name][2] = False with open("lockedname.txt", "w", encoding="utf-8") as f: json.dump(user, f) else: result = fun(*args, **kwargs) return inner @auth def tixian(name, cash_amount): pass @auth def zhuanzhuang(): pass
生成器和迭代器
1. 生成器和迭代器的区别?
生成器是迭代器的一种,能做所有迭代器的事,而且因为自动创建了 iter()和 next()方法,生成器简洁,高效。使用生成器节省内存。
2. 生成器有几种方式获取value?
next()
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
代码结构如下
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')
import logging def logger(filename,channel='terminal'): """ 日志方法 :param filename: log filename :param channel: 输出目的地,屏幕(҅terminal),文件(file),屏幕+文件(both) :return: """ log = logging.getLogger() log.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) fh = logging.FileHandler(filename, encoding="utf-8") fh.setLevel(logging.DEBUG) formatter = logging.Formatter( fmt="%(asctime)s %(message)s", datefmt="%Y/%m/%d %X", ) ch.setFormatter(formatter) fh.setFormatter(formatter) count = 0 while True: count += 1 mg = yield "ok"+str(count) # mg = yield meg = "[%s] %s"%(count,mg) if channel == 'terminal': log.addHandler(ch) log.info(meg) log.removeHandler(ch) elif channel == 'file': log.addHandler(fh) log.info(meg) log.removeHandler(fh) elif channel == 'both': log.addHandler(ch) log.addHandler(fh) log.info(meg) log.removeHandler(ch) log.removeHandler(fh) ll = logger("text.log",channel='both') print(ll.__next__()) print(ll.send('user alex login success')) ll.send('user lili login success') ll.send('user nana login success')
内置函数
1,用map来处理字符串列表,把列表中所有人都变成sb,比方alex_sb
map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。
def f(arg): arg = arg+"_sh" return arg lis = ["alex","lili","wangwu"] lis_new = map(f,lis) print(lis_new.__next__()) print(lis_new.__next__()) print(lis_new.__next__())
2,用filter函数处理数字列表,将列表中所有的偶数筛选出来
filter()用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
num
=
[
1
,
3
,
5
,
6
,
7
,
8
]
def f1(n): if n%2 == 0: return True else: return False num = [1,3,5,6,7,8] num_new = filter(f1,num) print(num_new.__next__()) print(num_new.__next__()) num_new2 = filter(lambda x:x%2 == 0,[1,3,5,6,7,8]) print(num_new2.__next__()) print(num_new2.__next__())
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
}
]
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 f2(i): if i['price'] > 100: return True portfolio_new = filter(f2,portfolio) # print(portfolio_new.__next__()) # print(portfolio_new.__next__()) for i in portfolio_new: print(i)