函数
*args 动态参数,万能参数
1 def func(*args): 2 print(args) 3 func(1,2,3,4,5,6,7)
执行输出:
(1, 2, 3, 4, 5, 6, 7)
结果是一个元组
顺序:
1 def func(a,b,c,d,*args,e='sex'): 2 print(a,b,c,d,args,e) 3 func(1,2,3,4,5,6,7,8,e='女')
执行输出:
1 2 3 4 (5, 6, 7, 8) 女
*args参数,可以不传,默认为空()
1 def func(a,b,c,d,*args,e='sex'): 2 print(a,b,c,d,args,e) 3 func(1,2,3,4,e='女')
执行输出:
1 2 3 4 () 女
**kwargs正确的位置
1 def func(a,b,c,d,*args,e='男',**kwargs): 2 print(a,b,c,d,args,e,kwargs) 3 func(1,2,3,4,5,6,7,v=3,m=7,h=9,e='女')
执行输出:
1 2 3 4 (5, 6, 7) 女 {'v': 3, 'h': 9, 'm': 7}
最终所有参数顺序:位置参数,*args,默认参数,**kwargs
分析代码
1 def extendList(val,list=[]): 2 list.append(val) 3 print(id(list)) #由于list是局部变量,只能在这里打印内存地址 4 return list 5 list1 = extendList(10) #val=10,list为默认参数,它是空列表,执行append,最终结果list1 = [10] 6 7 list2 = extendList(123,[]) #val=123,list的值被覆盖,开辟了一个新的内存地址,执行append,最终结果list2 = [123] 8 9 list3 = extendList('a') #val='a',list为默认参数,由于默认list用的是同一个内存地址,此时list为[10],执行append,最终结果list3 = [10,'a'] 10 11 print('list1=%s'%list1) #输出list1=[10,'a'],因为list1和list3使用的是默认值,共用一个内存地址。所以这2个值是一样的。 12 print('list2=%s'%list2) #输出list2=[123] 13 print('list3=%s'%list3) #输出list3=[10,'a']
执行输出:
1499634951496
1499634952520
1499634951496
list1=[10, 'a']
list2=[123]
list3=[10, 'a']
可以看出,list1和list3的list局部变量,用的是同一个内存地址,而list2用的是新的内存地址。
所以最终结果为:
list1=[10, 'a']
list2=[123]
list3=[10, 'a']
函数的执行时,*打散。
函数的定义时,*聚合。
1 from functools import wraps 2 def wrapper(f): # f = func1 3 @wraps(f) 4 def inner(*args,**kwargs): #聚合 5 #args (1,2,3) 6 '''执行函数之前的相关操作''' 7 ret = f(*args,**kwargs) # 打散 1,2,3 8 '''执行函数之后的相关操作''' 9 return ret 10 return inner 11 12 @wrapper # func1 = wrapper(func1) func1 = inner 13 def func1(*args): #args (1,2,3) 聚合 14 print(666) 15 return args 16 print(func1(*[1,2,3])) # inner(3,5) 打散
执行输出:
666
(1, 2, 3)
多个装饰器,装饰一个函数
1 def wrapper1(func): # func == f函数名 2 def inner1(): 3 print('wrapper1 ,before func') # 2 4 func() 5 print('wrapper1 ,after func') # 4 6 return inner1 7 8 def wrapper2(func): # func == inner1 9 def inner2(): 10 print('wrapper2 ,before func') # 1 11 func() 12 print('wrapper2 ,after func') # 5 13 return inner2 14 15 @wrapper2 # f = wrapper2(f) 里面的f==inner1 外面的f == inner2 离f()远 后执行 16 @wrapper1 # f = wrapper1(f) 里面的f==函数名f 外面的f == inner1 离f()近 先执行 17 def f(): # 3 18 print('in f') 19 20 f() # inner2()
执行输出:
wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func
哪个离函数近,哪个先计算
最底下的先执行
1.
写函数,返回一个扑克牌列表,里面有
52
项,每一项是一个元组
例如:[(
'红心'
,
2
),(
'草花'
,
2
), …(
'黑桃'
,
'A'
)]
1 def func(li): 2 l = [] 3 for i in li: 4 #A用1表示,2~10表示数字牌,JQK分别表示11,12,13 5 for j in range(1,14): 6 if j == 1: 7 j = 'A' 8 elif j == 11: 9 j = 'J' 10 elif j == 12: 11 j = 'Q' 12 elif j == 13: 13 j = 'K' 14 l.append((i,j)) 15 return l 16 print(func(['草花', '黑桃', '红桃', '方片']))
在编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码。这个作业之上进行升级操作:
设置两套密码,一套为京东账号密码,一套为淘宝账号密码保存在文件中。
设置四个函数,分别代表 京东首页,京东超市,淘宝首页,淘宝超市。
循环打印四个选项:东首页,京东超市,淘宝首页,淘宝超市。
供用户选择,用户输入选项后,执行该函数,四个函数都加上认证功能,只要登陆成功一次,在选择其他函数,后续都无需输入用户名和密码。
相关提示:用带参数的装饰器。装饰器内部加入判断,验证不同的账户密码。
1 dic = { 2 'username':None, 3 'status':False, 4 } 5 6 i = 0 7 def login(flag): 8 def wrapper(func): 9 def inner(*args, **kwargs): 10 #判断用户状态是否为True 11 if dic['status']: 12 ret = func(*args, **kwargs) 13 return ret 14 else: 15 global i 16 while i < 3: 17 username = input('请输入用户名(用%s账号):' % flag).strip() 18 password = input('请输入密码:').strip() 19 with open('user_pwd',encoding='utf-8') as f1: 20 #读取一行,因为文件只有一行内容 21 msg_dic = eval(f1.readline()) 22 # {'微信': {'password': '123', 'username': '老男孩'}, 'qq': {'password': '123', 'username': '老男孩1'}} 23 if username == msg_dic[flag]['username'] and password == msg_dic[flag]['password']: 24 #修改全局变量,这里不用global,因为它是可变类型 25 dic['username'] = username 26 dic['status'] = True 27 #执行被装饰的函数 28 ret = func(*args, **kwargs) 29 return ret 30 else: 31 print('您输入的用户或者密码错误,请重新输入,还有%s次机会' % (2-i)) 32 i += 1 33 34 return inner 35 return wrapper 36 37 @login('微信') 38 def taobao_home(): 39 print('淘宝首页') 40 41 @login('微信') 42 def taobao_shop(): 43 print('淘宝超市') 44 45 @login('qq') 46 def jingdong_home(): 47 print('京东首页') 48 49 @login('qq') 50 def jingdong_shop(): 51 print('京东超市') 52 53 #菜单列表,建议使用此方式 54 choice_dict = { 55 #序号:函数名 56 1: taobao_home, 57 2: taobao_shop, 58 3: jingdong_home, 59 4: jingdong_shop, 60 5: exit, 61 } 62 63 while True: 64 print('1 淘宝首页\n2 淘宝超市\n3 京东首页\n4 京东超市\n5 退出') 65 choice_num = input('请选择输入的序号:').strip() 66 if choice_num.isdigit(): 67 choice_num = int(choice_num) 68 #判断数字范围 69 if 0 < choice_num <= len(choice_dict): 70 #执行函数 71 choice_dict[choice_num]() 72 else: 73 print('请输入范围内的序号') 74 else: 75 print('您输入的有非法字符,请重新输入')