函数

*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('您输入的有非法字符,请重新输入')

 

posted @ 2018-09-17 21:46  北三环的雪  阅读(115)  评论(0编辑  收藏  举报