第4章 函数

一. 函数的嵌套

     1. 函数的嵌套调用

         定义:在电泳函数的过程中,调用的其他函数

 1 #函数嵌套的调用
 2 def max2(x,y):
 3     if x > y:
 4         return x
 5     else:
 6         return y
 7 
 8 def max3(a,b,c,d):
 9     res=max2(a,b)
10     res2=max2(res,c)
11     res3=max2(res2,d)
12     return res3
13 
14 res=max3(1,2,3,4)
15 print(res)
16 
17 #函数嵌套的定义:
18 def foo():
19     def foo1():
20         def foo2():
21             def foo3():
22                 print('from foo3')
23             foo3()
24         foo2()
25     foo1()
26 foo()

二.名称空间和作用域

    1. 名称空间:存放名字和变量值绑定关系的地方,有三种名称空间:内置名称空间,全局名称空间,局部名称空间。

        内置名称空间:在python解释器启动时产生,存放一些python内置名字。

        全局名称空间:在执行文件时产生,存放文件级别定义的名字。

        局部名称空间:在执行文件过程中,如果调用了函数,则产生该函数的局部名称空间,用来存放该函数内定义的名字,该名字在函数调用时生效,在函数调用结束后失效。

        名字的加载顺序是:内置====》全局 ====》局部

        名字的查找顺序是:局部====》全局 ====》内置

     2. 作用域:即作用范围

          作用域关系是在函数定义阶段就已经固定,与函数的调用无关。

         2.1 全局作用域:全局存活,全局有效(globals())

 1 max=1111
 2 def foo():
 3     def foo1():
 4         def foo2():
 5             def foo3():
 6                 print(max)
 7             foo3()
 8         foo2()
 9     foo1()
10 foo()
11 
12 #global 在函数内引用全局变量,可以修改全局变量
13 x=1111
14 def foo():
15     global x
16     x=100
17     def foo1():
18         def foo2():
19             def foo3():
20                 print(x)
21             foo3()
22         foo2()
23     foo1()
24 foo()
25 print(x)
View Code

        2.2  局部作用域:临时存活,局部有效(locals())

 1 x=111111111111111
 2 def foo():
 3     def foo1():
 4         def foo2():
 5             x=100
 6             def foo3():
 7                 print(x)
 8             foo3()
 9         foo2()
10     foo1()
11 foo()
12 print(x)
View Code

       2.3 查找作用域globals(),locals()及globals,nonlocal

 1 #globals(),locals()
 2 x=111111111
 3 def foo():
 4     def f1():
 5         x=1
 6         y=2
 7         def f2():
 8             print(x,y)
 9             print(globals())  #可以查看全局的作用域
10             print(locals())   #可以查看在函数内部的局部作用域
11         f2()
12     f1()
13 foo()
14 
15 #global,nonlocal
16 x=111111111
17 def foo():
18     def f1():
19         global x          #把全局变量引进函数内,可修改全局变量值,这个修改是全局有效
20         x=1
21         y=2
22         def f2():
23             print(x,y)
24         f2()
25     f1()
26 foo()
27 print(x)
28 
29 x=11111
30 def f1():
31     def f2():
32         x=1
33         y=2222
34         def f3():
35             nonlocal x   #只修改函数内部的变量值,局部有效
36             x=3
37             print(x)
38         f3()
39     f2()
40 f1()
41 print(x)
View Code

      LEGB代表名字的查找顺序:locals----》enclosing function----》globals-----》__builtins__

      locals 代表函数内的名字,包括局部变量和形参

      enclosing function 外部嵌套函数的名字空间(闭包函数中比较常见)

      __builtins__  内置模块的名字空间

四. 闭包函数

      闭包函数:定义在函数内部的函数,内部函数包含外部作用域而非全局作用域的引用。

      闭包函数的应用:惰性计算,延迟计算

 1 import requests #pip3 install requests
 2 def get(url):
 3     return requests.get(url)
 4 
 5 def index(url):
 6     def get():
 7         # return requests.get(url).text
 8         print(requests.get(url).text)
 9     return get
10 python_web=index('http://www.python.org')
11 print(python_web())
View Code

 五.装饰器(闭包函数的一种应用场景)

     装饰器本身可以是任意可调用对象,被装饰的对象本身也可以是任意可调用对象。

     装饰器遵循的原则:1.不改变被装饰对象的源代码,2不修改被装饰对象的调用方式。

     装饰器的目的:在遵循1和2 的原则情况下,为被装饰对象添加新功能。

     装饰器名,必须写在被装饰对象的正上方,单独一行

 1 import time
 2 def timmer(func):
 3     def warpper(*args,**kwargs):
 4         statr_time=time.time()
 5         res=func(*args,**kwargs)
 6         stop_time=time.time()
 7         print('%s'%(statr_time-stop_time))
 8         return res
 9     return warpper
10 @timmer
11 def index():
12     time.sleep(3)
13     print('welcome to index')
14 @timmer # home=timmer(home)
15 def home():
16     time.sleep(2)
17     print('welcome to home page')
18 
19 index()
20 home()
View Code

     装饰器函数:wraps

 1 import time
 2 from functools import wraps
 3 def timmer(func):
 4     @wraps(func)
 5     def warpper(*args,**kwargs):
 6         statr_time=time.time()
 7         res=func(*args,**kwargs)
 8         stop_time=time.time()
 9         print('%s'%(statr_time-stop_time))
10         return res
11     return warpper
12 @timmer
13 def index():
14     '''这是测试'''
15     time.sleep(3)
16     print('welcome to index')
17 @timmer # home=timmer(home)
18 def home():
19     time.sleep(2)
20     print('welcome to home page')
21 
22 print(index.__doc__)
23 print(help(index))
View Code

     多装饰器:一个函数可以有多个函数

 1 import time
 2 from functools import wraps
 3 current_user={'user':None}
 4 
 5 def timmer(func):
 6     @wraps(func)
 7     def wrapper(*args,**kwargs):
 8         start=time.time()
 9         res=func(*args,**kwargs)
10         stop=time.time()
11         print('run time is %s' %(stop-start))
12         return res
13     return wrapper
14 def auth(auth_type='file'):
15     def deco(func):
16         def wrapper(*args, **kwargs):
17             if auth_type == 'file':
18                 if current_user['user']:
19                     return func(*args, **kwargs)
20                 name = input('name: ').strip()
21                 password = input('password: ').strip()
22 
23                 with open('db.txt', encoding='utf-8') as f:
24                     user_dic = eval(f.read())
25                 if name in user_dic and password == user_dic[name]:
26                     res = func(*args, **kwargs)
27                     current_user['user'] = name
28                     return res
29                 else:
30                     print('user or password error')
31             elif auth_type == 'mysql':
32                 print('mysql')
33 
34             elif auth_type == 'ldap':
35                 print('ldap')
36             else:
37                 print('not valid auth_type')
38         return wrapper
39     return deco
40 
41 
42 #多装饰器
43 @timmer #index=timmer(wrapper)
44 @auth() # @deco #index=deco(index) #wrapper
45 def index():
46     '''这是index函数'''
47     time.sleep(3)
48     print('welcome to index')
49     return 123
50 
51 # print(index.__doc__)
52 # print(help(index))
53 
54 index()
View Code

  六.装饰器练习

 1 一:编写函数,(函数执行的时间是随机的)
 2 二:编写装饰器,为函数加上统计时间的功能
 3 三:编写装饰器,为函数加上认证的功能
 4 四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
 5 注意:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式
 6 五:编写装饰器,为多个函数加上认证功能,要求登录成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录
 7 六:编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
 8 七:为题目五编写装饰器,实现缓存网页内容的功能:
 9 具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中
10 扩展功能:用户可以选择缓存介质/缓存引擎,针对不同的url,缓存到不同的文件中
11 八:还记得我们用函数对象的概念,制作一个函数字典的操作吗,来来来,我们有更高大上的做法,在文件开头声明一个空字典,然后在每个函数前加上装饰器,完成自动添加到字典的操作
12 九 编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017-07-21 11:12:11 f1 run写入到日志文件中,日志文件路径可以指定
13 注意:时间格式的获取
14 import time
15 time.strftime('%Y-%m-%d %X')
  1 # 一:编写函数,(函数执行的时间是随机的)
  2 import time
  3 def index():
  4     time.sleep(3)
  5     print('welcome to index')
  6 # 二:编写装饰器,为函数加上统计时间的功能
  7 import time
  8 def timmer(func):
  9     def wapepr(*args,**kwargs):
 10         start_time=time.time()
 11         res=func(*args,**kwargs)
 12         stop_time=time.time()
 13         print('%s'%(stop_time-start_time))
 14         return res
 15     return wapepr
 16 @timmer
 17 def index():
 18     time.sleep(3)
 19     print('welcome to index')
 20 index()
 21 # 三:编写装饰器,为函数加上认证的功能
 22 import time
 23 current_user={'user':None}
 24 def authen(func):
 25     def user_authen(*args,**kwargs):
 26         if current_user['user']:
 27              return func(*args,**kwargs)
 28         name=input('请输入名字:').strip()
 29         password=input('请输入密码:').strip()
 30         with open('db.txt','r',encoding='utf-8') as f:
 31             user_dic=eval(f.read())
 32             if name in user_dic and user_dic[name] == password:
 33                 print('登录成功')
 34                 current_user['user']=name
 35                 res=func(*args,**kwargs)
 36                 return res
 37             else:
 38                 print('用户名或密码错误!')
 39     return  user_authen
 40 @authen
 41 def home():
 42     time.sleep(2)
 43     print('welcome to home page')
 44 
 45 @authen
 46 def index():
 47     time.sleep(3)
 48     print('welcome to index')
 49 index()
 50 home()
 51 # 四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
 52 # 注意:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式
 53 import time
 54 current_user={'user':None}
 55 def authen(func):
 56     def user_authen(*args,**kwargs):
 57         if current_user['user']:
 58              return func(*args,**kwargs)
 59         name=input('请输入名字:').strip()
 60         password=input('请输入密码:').strip()
 61         with open('db.txt','r',encoding='utf-8') as f:
 62             user_dic=eval(f.read())
 63             if name in user_dic and user_dic[name] == password:
 64                 print('登录成功')
 65                 current_user['user']=name
 66                 res=func(*args,**kwargs)
 67                 return res
 68             else:
 69                 print('用户名或密码错误!')
 70     return  user_authen
 71 @authen
 72 def home():
 73     time.sleep(2)
 74     print('welcome to home page')
 75 
 76 @authen
 77 def index():
 78     time.sleep(3)
 79     print('welcome to index')
 80 index()
 81 home()
 82 # 五:编写装饰器,为多个函数加上认证功能,要求登录成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录
 83 import time
 84 def timmer(func):
 85     def wraps(*args,**kwargs):
 86         s1=time.time()
 87         res=func(*args,**kwargs)
 88         s2=time.time()
 89         print('%s'%(s2-s1))
 90 current_user={'user':None,'logintime':None,'timeout':0.000003}
 91 def authen(func):
 92     def user_authen(*args,**kwargs):
 93         if current_user['user']:
 94              tomeout=time.time()-current_user['logintime']
 95              if tomeout < current_user['timeout']:
 96                     return func(*args,**kwargs)
 97         name=input('请输入名字:').strip()
 98         password=input('请输入密码:').strip()
 99         with open('db.txt','r',encoding='utf-8') as f:
100             user_dic=eval(f.read())
101             if name in user_dic and user_dic[name] == password:
102                 print('登录成功')
103                 current_user['user']=name
104                 current_user['logintime']=time.time()
105                 res=func(*args,**kwargs)
106                 return res
107             else:
108                 print('用户名或密码错误!')
109     return  user_authen
110 @authen
111 def home():
112     time.sleep(2)
113     print('welcome to home page')
114 
115 @authen
116 def index():
117     time.sleep(3)
118     print('welcome to index')
119 index()
120 home()
121 # 六:编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
122 import requests
123 def index(url):
124     def get():
125         # return requests.get(url).text
126         print(requests.get(url).text)
127     return get
128 web=index('http://www.python.org')
129 web()
130 # 七:为题目五编写装饰器,实现缓存网页内容的功能:
131 # 具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中
132 import requests
133 import os
134 cache_file='cache.txt'
135 def make_cache(func):
136     def wrapper(*args,**kwargs):
137         if not os.path.exists(cache_file):
138             with open(cache_file,'w'):pass
139 
140         if os.path.getsize(cache_file):
141             with open(cache_file,'r',encoding='utf-8') as f:
142                 res=f.read()
143         else:
144             res=func(*args,**kwargs)
145             with open(cache_file,'w',encoding='utf-8') as f:
146                 f.write(res)
147         return res
148     return wrapper
149 
150 @make_cache
151 def get(url):
152     return requests.get(url).text
153 
154 
155 # res=get('https://www.python.org')
156 
157 # print(res)
158 # 扩展功能:用户可以选择缓存介质/缓存引擎,针对不同的url,缓存到不同的文件中
159 import requests,os,hashlib
160 engine_settings={
161     'file':{'dirname':'./db'},
162     'mysql':{
163         'host':'127.0.0.1',
164         'port':3306,
165         'user':'root',
166         'password':'123'},
167     'redis':{
168         'host':'127.0.0.1',
169         'port':6379,
170         'user':'root',
171         'password':'123'},
172 }
173 
174 def make_cache(engine='file'):
175     if engine not in engine_settings:
176         raise TypeError('egine not valid')
177     def deco(func):
178         def wrapper(url):
179             if engine == 'file':
180                 m=hashlib.md5(url.encode('utf-8'))
181                 cache_filename=m.hexdigest()
182                 cache_filepath=r'%s/%s' %(engine_settings['file']['dirname'],cache_filename)
183 
184                 if os.path.exists(cache_filepath) and os.path.getsize(cache_filepath):
185                     return open(cache_filepath,encoding='utf-8').read()
186 
187                 res=func(url)
188                 with open(cache_filepath,'w',encoding='utf-8') as f:
189                     f.write(res)
190                 return res
191             elif engine == 'mysql':
192                 pass
193             elif engine == 'redis':
194                 pass
195             else:
196                 pass
197 
198         return wrapper
199     return deco
200 
201 @make_cache(engine='file')
202 def get(url):
203     return requests.get(url).text
204 
205 # print(get('https://www.python.org'))
206 print(get('https://www.baidu.com'))
207 # 八:还记得我们用函数对象的概念,制作一个函数字典的操作吗,来来来,我们有更高大上的做法,在文件开头声明一个空字典,然后在每个函数前加上装饰器,完成自动添加到字典的操作
208 route_dic={}
209 def make_route(name):
210     def deco(func):
211         route_dic[name]=func
212     return deco
213 @make_route('select')
214 def func1():
215     print('select')
216 @make_route('insert')
217 def func2():
218     print('insert')
219 @make_route('update')
220 def func3():
221     print('update')
222 print(route_dic)
223 # 九 编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017-07-21 11:12:11 f1 run写入到日志文件中,日志文件路径可以指定
224 # 注意:时间格式的获取
225 # import time
226 # time.strftime('%Y-%m-%d %X')
227 import time
228 import os
229 
230 def logger(logfile):
231     def deco(func):
232         if not os.path.exists(logfile):
233             with open(logfile,'w'):pass
234 
235         def wrapper(*args,**kwargs):
236             res=func(*args,**kwargs)
237             with open(logfile,'a',encoding='utf-8') as f:
238                 f.write('%s %s run
' %(time.strftime('%Y-%m-%d %X'),func.__name__))
239             return res
240         return wrapper
241     return deco
242 
243 @logger(logfile='a.log')
244 def index():
245     print('index')
246 
247 index()
View Code

 七.迭代器

     迭代的概念:重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果就是下一次迭代的初始值。

     可迭代对象有:

s='hello'
l=['a','b','c','d']
t=('a','b','c','d')
dic={'name':'egon','sex':'m',"age":18}
set1={1,2,3}
f=open('db.txt')
s.__iter__()
l.__iter__()
t.__iter__()
dic.__iter__()
set1.__iter__()
f.__iter__()

      迭代器:可迭代对象执行内置的__iter__方法,得到的结果就是迭代器。

      迭代器对象:1.有__iter__方法,执行得到的结果仍是迭代本身,2.有__next__方法。

dic={'name':'egon','sex':'m',"age":18}
i=dic.__iter__()
print(i)  #iterator迭代器

#i.__next__()  #next(i)
print(next(i))
print(next(i))
print(next(i))
print(next(i))  #StopIteration

    不依赖于索引的取值方法:

l=['a','b','c','d']
dic={'name':'egon','sex':'m',"age":18}
iter_l=iter(l)
iter_dic=iter(dic)
while True:
    try:
        # print(next(iter_l))
        k=next(iter_dic)
        print(k,dic[k])
    except StopIteration:
        break

   迭代器的优点:

        1. 提供了一种不依赖索引的取值方法。

        2. 迭代器本身,比其他数据类型更省内存(一次只有一行数据在内存)。

 1 l=['a','b','c','d']
 2 i=iter(l)
 3 
 4 dic={'a':1,'b':2}
 5 x=dic.keys()
 6 print(x)
 7 i=x.__iter__()
 8 
 9 with open('a.txt') as f:
10     print(next(f),end='')
11     print(next(f),end='')
12     print(next(f),end='')
13     f.read()
View Code

   迭代器的缺点:

        1. 一次性,只能向前,不能回退,不如索引取值方便。

        2. 无法预知什么时候取值结束,即无法预知长度。

   for 循环原理,就是迭代循环

 1 l=['a','b','c','d']
 2 for item in l: #iter_l=l.__iter__()
 3     print(item)
 4 
 5 for item in {1,2,3,4}:
 6     print(item)
 7 
 8 with open('a.txt') as f:
 9     # for line in f: #i=f.__iter__()
10     #     print(line)
11     print(f is f.__iter__())
View Code

   判断可迭代对象与迭代器对象

 1 from collections import Iterable,Iterator
 2 s='hello'
 3 l=['a','b','c','d']
 4 t=('a','b','c','d')
 5 dic={'name':'egon','sex':'m',"age":18}
 6 set1={1,2,3}
 7 f=open('a.txt')
 8 
 9 print(isinstance(s,Iterable))    #判断是否是可迭代对象
10 print(isinstance(l,Iterable))
11 print(isinstance(t,Iterable))
12 print(isinstance(dic,Iterable))
13 print(isinstance(set1,Iterable))
14 print(isinstance(f,Iterable))
15 
16 print(isinstance(s,Iterator))     #判断是否是迭代器对象
17 print(isinstance(l,Iterator))
18 print(isinstance(t,Iterator))
19 print(isinstance(dic,Iterator))
20 print(isinstance(set1,Iterator))
21 print(isinstance(f,Iterator))
View Code

八. 生成器

       生成器:在函数内部包含yield关键,那么函数执行的结果就是生成器。

      yield的功能:

               1.把函数的结果做成生成器(以一种优雅的方式封装__iter__,__next__)

               2. 函数的暂停及再继续运行状态是由yield控制。

 1 def func():
 2     print('first')
 3     yield 11111111
 4     print('second')
 5     yield 2222222
 6     print('third')
 7     yield 33333333
 8     print('fourth')
 9 
10 
11 g=func()
12 print(g)
13 from collections import Iterator
14 print(isinstance(g,Iterator))
15 
16 print(next(g))
17 print('======>')
18 print(next(g))
19 print('======>')
20 print(next(g))
21 print('======>')
22 
23 for i in g: #i=iter(g)
24     print(i)
View Code

     yield 和return的比较

      相同:都有返回值的功能

      不同:return只能返回一次值,yield可以返回多次值

     应用一:

 1 def my_range(start,stop):
 2     while True:
 3         if start == stop:
 4             raise StopIteration   #遇到StopIteration 结束
 5         yield start #2
 6         start+=1 #3
 7 
 8 g=my_range(1,3)
 9 # print(next(g))
10 # print(next(g))
11 # print(next(g))
12 
13 for i in my_range(1,5):
14     print(i)
View Code

     应用二:管道  tailf access.log|grep 'error'

 1 import time
 2 def tailf(filepath):
 3     with open(filepath,'r',encoding='utf-8') as f:
 4         f.seek(0, 2)
 5         while True:
 6             line=f.readline()
 7             if line:
 8                 yield line
 9             else:
10                 time.sleep(0.2)
11 
12 def grep(pattern,lines):
13     for line in lines:
14         if pattern in line:
15             print(line,end='')
16 
17 grep('error',tailf('access.log'))
View Code

九.  三元表达式,列表推导式,生成器表达式

      1. 三元表达式

 1 def foo(x):
 2     if x > 3:
 3         return 'ok'
 4     else:
 5         return 'no'
 6 
 7 x=10
 8 res=x if x > 3 else 'no'
 9 print(res)
10 
11 def max2(x,y):
12     return x if x > y else y
13 print(max2(1,3))
14 
15 name='egon'
16 print('SB' if name == 'alex' else 'shuai')
View Code

      2. 列表推导式

 1 #------------------1:引子
 2 #生一筐鸡蛋
 3 egg_list=[]
 4 for i in range(10):
 5     egg_list.append('鸡蛋%s' %i)
 6 print(egg_list)
 7 
 8 #列表解析
 9 egg_list=['鸡蛋%s' %i for i in range(10)]
10 print(egg_list)
11 
12 #列表内每个数的2倍生成一个新列表
13 nums = [1, 2, 3, 4, 5, 6]
14 nums_new=[]
15 for i in nums:
16     nums_new.append(i**2)
17 print(nums_new)
18 
19 #列表解析大于3的数的2倍生成一个新列表
20 nums_new=[i**2 for i in nums if i > 3 ]
21 print(nums_new)
View Code

      3. 生成器表达式

 1 g=('egg%s' %i for i in range(1000))
 2 print(g)
 3 print(next(g))
 4 print(next(g))
 5 print(next(g))
 6 
 7 with open('a.txt',encoding='utf-8') as f:
 8     # res=max((len(line) for line in f))
 9     res=max(len(line) for line in f)
10     print(res)
11 #
12 print(max([1,2,3,4,5,6]))
13 
14 with open('a.txt',encoding='utf-8') as f:
15     g=(len(line) for line in f)
16     print(max(g))
17     print(max(g))
View Code

      4.声明式编程应用

 1 res=sum(i for i in range(3))
 2 print(res)
 3 
 4 with open('db.txt',encoding='utf-8') as f:
 5     l=(float(line.split()[1])*int(line.split()[2]) for line in f)
 6     print(sum(l))
 7 
 8     l=[]
 9     for line in f:
10        goods=line.split()
11        price=float(goods[1])
12        count=int(goods[2])
13        cost=price * count
14        l.append(cost)
15 
16     print(sum(l)) #196060.0
17 
18 # [{'name': 'apple', 'price': 333, 'count': 3}, ]
19 with open('db.txt',encoding='utf-8') as f:
20     info=[{'name':line.split()[0],
21       'price':float(line.split()[1]),
22       'count':int(line.split()[2])} for line in f if float(line.split()[1]) >= 30000]
23     print(info)
View Code

十. 作业

      模拟实现一个ATM+购物商城程序

 1 额度 15000或自定义
 2 实现购物商城,买东西加入 购物车,调用信用卡接口结账
 3 可以提现,手续费5%
 4 每月22号出账单,每月10号为还款日,过期未还,按欠款总额 万分之5 每日计息
 5 支持多账户登录
 6 支持账户间转账
 7 记录每月日常消费流水
 8 提供还款接口
 9 ATM记录操作日志 
10 提供管理接口,包括添加账户、用户额度,冻结账户等。。。
11 用户认证用装饰器
 1 # 2.实现购物商城,买东西加入 购物车,调用信用卡接口结账
 2 #商品菜单
 3 goods_info_dic = {}
 4 def menu():
 5     with open('db.txt', 'r', encoding='utf-8') as f:
 6         goods_dic = eval(f.read())
 7         i = 0
 8         for item in goods_dic:
 9             goods_info_dic[i] = {'name': item, 'price': goods_dic[item], 'nums': 1}
10             i += 1
11         print('以下是所有商品信息'.center(38, '*'))
12         for line in goods_info_dic:
13             print('商品编号: ', line, ' name:', goods_info_dic[line]['name'], ' price:  ¥', goods_info_dic[line]['price'])
14 #加入购物车
15 user_goods=[]
16 def googs():
17      if current_user['user']:
18          menu()
19          count=input('请输入商品编号:').strip()
20          if count.isdigit():
21              count=int(count)
22              if count < len(goods_info_dic):
23                  if count not in user_goods:
24                      user_goods.append(count,user_goods[count])
25                  else:
26                      pass
27 menu()
28 count=input('请输入商品编号:').strip()
29 if count.isdigit():
30      count=int(count)
31      if count < len(goods_info_dic):
32          if count not in user_goods:
33              user_goods[count]=goods_info_dic[count]
34          else:
35              user_goods[count]['nums']+=1
36 mun = input('请输入购买商品的数量:').strip()
37 if mun.isdigit():
38    if  user_goods[count]['nums'] == 1:
39         user_goods[count]['nums'] = int(mun)
40    else:
41        user_goods[count]['nums'] = int(mun)
42    print('购物车里的商品:',user_goods)
43 
44 
45 def home():
46     time.sleep(2)
47     print('welcome to home page')
48 
49 # 5.支持多账户登录
50 import time
51 current_user={'user':None}
52 def authen(func):
53     def user_authen(*args,**kwargs):
54         if current_user['user']:
55             return func(*args,**kwargs)
56         name=input('请输入名字:').strip()
57         password=input('请输入密码:').strip()
58         with open('user','r',encoding='utf-8') as f:
59             user_dic=eval(f.read())
60             if name in user_dic and user_dic[name] == password:
61                 print('登录成功')
62                 current_user['user']=name
63                 res=func(*args,**kwargs)
64                 return res
65             else:
66                 print('用户名或密码错误!')
67     return  user_authen
68 # 6.支持账户间转账
69 # 7.记录每月日常消费流水
70 # 8.提供还款接口
71 # 9.ATM记录操作日志
72 # 10.提供管理接口,包括添加账户、用户额度,冻结账户等。。。
73 # 11.用户认证用装饰器
View Code

   

     

     

       

          

      

         

         

      

   

原文地址:https://www.cnblogs.com/fanglingen/p/7228230.html