函数基础(二)
函数的嵌套
函数嵌套定义
函数内部定义的函数,无法在函数外部使用内部定义的函数,在函数中见到()就是函数的调用,如果没有()就不是函数的调用
def fun1():
print(1111)
def fun2():
print(222)
fun1()
fun2()
print(222b)
222
1111
222b
名称空间与作用域
名称空间:在python中函数执行时会开辟出一个空间,每当遇到一个变量的时候,就会把变量名和值之间的关系记录下来,但是当遇到函数定义的时候,解释器只是把函数名读入内存,表示这个函数已经存在了,至于函数内部的逻辑和变量,解释器暂时并不关心,但是当函数被调用的时候解释器才会根据函数内部变量占用的空间也会随着函数执行完毕而被清空.
def fun():
a = 10
print(a)
fun()
print(a) # 这时a已经被清理掉了
函数调用的过程,先记录变量名与值之间的关系,当被调用时才会去开辟内存地址,执行完毕之后就清掉函数内部的变量
- 我们在存放名字的时候值和名字的关系的空间就叫命名空间,变量存储时就是存储在这片空间之中
- 命名空间的分类:
- 全局命名空间--->我们在py文件中,函数外声明的变量都属于全局命名空间
- 局部命名空间--->在函数声明的变量会放在局部命名空间
- 内置命名空间--->存放python解释器为我们提供名字,list,tuple,str等这些都是内置命名空间
- 加载顺序:
- 内置命名空间--->全局命名空间--->局部命名空间(函数被执行时)
- 执行顺序:
1. 局部命名空间--->全局命名空间--->内置命名空间
函数的作用域
作用域:作用域就是作用范围,按照生效的范围来看分为全局作用域和局部作用域
全局作用域:
1. 全局作用域:包含内置命名空间和全局命名空间,在整个文件的任何位置都可以使用(遵循从上到下逐行执行)
2. 局部作用域:只有函数内部才可以使用
global和nonlocal
首先我们在写代码的时候,会声明一个全局变量,然后再局部调用这个变量,当需要改变这个全局变量的时候就需要用到global
a = 100
def func():
global a # 在这个地方加上global表明,将会修改掉全局变量
a = 28
print(a)
func()
print(a)
nonlocal只是修改上一层的变量,如果上一层没有变量就会继续向上去找,一层一层往上找,但是并不会去找到全局变量
a = 10
def func1():
a = 20
def func2():
nonlocal a
a = 30
print(a)
func2()
print(a)
func1()
# 结果:
# 加了nonlocal
30
30
# 不加nonlocal
30
20
闭包函数
什么是闭包
闭包:闭包是封闭(函数内部函数),包是包含(该内部函数对外部作用域而非全局作用域的变量的引用),闭包指的是:函数的内部函数对外部作用域而非全局作用域的引用.
提示:之前我们都是通过参数将外部的值传给参数,闭包提供一种思路
def outter():
x = 1
def inner():
print(x)
return inner
f = outter
def f2():
x = 2
f()
f2()
函数的传参方式
- 函数传参方式一: 使用参数的形式
def func(x):
print(x)
func(1)
- 函数传参方式二:包给函数
def outter(x):
def inner():
print(x)
return inner
outter()
闭包的应用
应用领域:延迟计算(原来是传参直接就计算,现在是抱起来)、爬虫领域
装饰器
无参装饰器
什么是装饰器
装饰器指的是为被装饰对象添加额外功能.因此定义装饰器就是定义一个函数,只不过该函数的功能是用来为其他函数添加额外的功能
需要注意的是:
- 装饰器本身其实是可以任意可调用的对象
- 被装饰的对象也可以是任意可调用的对象
为什么要用装饰器
当线上的项目已经使用发现需要修改或者添加一个什么功能的时候,我们又不能对原来的函数进行修改,这个时候就需要用装饰器.装饰器遵循的是开放封闭原则,即对原函数是封闭的,对功能拓展是开放的
装饰器遵循两大原则:
1. 不修改被装饰对象的源代码
2. 不修改被装饰对象的调用方式
怎么用装饰器
简易的装饰器
import time
def index():
start = time.time()
print('welcome to index')
time.sleep(1)
end = time.time()
print(F"index run time is {end - start}")
index()
语法糖
在被装饰函数正上方,并且是单独一行写上装饰器名
,就可以直接调用原装饰器
有参装饰器
import time
current_user = {'username': None}
def login(func):
# func = 最原始的index
def wrapper(*args, **kwargs):
if current_user['username']:
res = func(*args, **kwargs)
return res
user = input('username: ').strip()
pwd = input('password: ').strip()
if user == 'nick' and pwd == '123':
print('login successful')
current_uesr['usre'] = user
res = func(*args, **kwargs)
return res
else:
print('user or password error')
return wrapper
@login
def home(name):
print(f"welcome {name} to home page")
time.sleep(1)
return name
@login
def index():
print('welcome to index')
time.sleep(1)
return 123
res = index()
装饰器模板
def deco(func):
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper
无参装饰器
import time
current_user = {'username': None}
def login(func):
# func = 最原始的index
def wrapper(*args, **kwargs):
if current_user['username']:
res = func(*args, **kwargs)
return res
user = input('username: ').strip()
pwd = input('password: ').strip()
engine = 'file'
if engine == 'file':
print('base of file')
if user == 'nick' and pwd == '123':
print('login successful')
current_uesr['usre'] = user
res = func(*args, **kwargs)
return res
else:
print('user or password error')
elif engine == 'mysql':
print('base of mysql')
elif engine == 'mongodb':
print('base of mongodb')
else:
print('default')
return wrapper
@login
def home(name):
print(f"welcome {name} to home page")
time.sleep(1)
@login
def index():
print('welcome to index')
time.sleep(1)
res = index()
三层闭包
import time
current_uesr = {'username': None}
def auth(engine='file'):
def login(func):
# func = 最原始的index
def wrapper(*args, **kwargs):
if current_user['username']:
res = func(*args, **kwargs)
return res
user = input('username: ').strip()
pwd = input('password: ').strip()
if engine == 'file':
print('base of file')
if user == 'nick' and pwd == '123':
print('login successful')
current_uesr['usre'] = user
res = func(*args, **kwargs)
return res
else:
print('user or password error')
elif engine == 'mysql':
print('base of mysql, please base of file')
elif engine == 'mongodb':
print('base of mongodb, please base of file')
else:
print('please base of file')
return wrapper
return login
@auth(engine='mysql')
def home(name):
print(f"welcome {name} to home page")
time.sleep(1)
@auth(engine='file')
def index():
print('welcome to index')
time.sleep(1)
res = index()
简易的购物车
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import datetime
now_time = datetime.datetime.now()
login_list = []
# time_now = time.strftime('%Y.%m.%d',time.localtime(time.time()))
is_login = False
def register():
'''注册'''
# is_login = False
while True:
usename_register = input('请输入注册名:>>>').strip()
pwd_register = input('请输入注册密码:>>>').strip()
if ' ' in usename_register or ' ' in pwd_register:
print('注册名或者密码中不能含有空格')
continue
with open('user_info.txt', 'r',encoding='utf8') as fr:
for user in fr:
user_list = user.strip('
').split(':')
if usename_register == user_list[0]:
print('用户名已存在')
break
else:
with open('user_info.txt', 'a', encoding='utf8') as fw:
fw.write(f'{usename_register}:{pwd_register}
')
print('注册成功')
login()
break
def login():
'''登录'''
login_count = 0
global is_login
if is_login == True:
print('无需重复登录')
return
while login_count < 3:
usename_login = input('请输入你的登录名:>>>').strip()
pwd_login = input('请输入你的登录密码:>>>').strip()
login_count += 1
user_dict = dict()
with open('user_info.txt', 'r', encoding='utf8') as fr:
for user in fr:
user_list = user.strip('
').split(':')
user_dict = {user_list [0] : user_list[1]}
if usename_login == user_list[0] and pwd_login == user_list[1]:
login_list.append(usename_login)
# print(login_list)
print(f'{usename_login}登录成功'.center(50,'-'))
with open(f'{login_list[0]}shopping_history.txt', 'a',encoding='utf8')as f:
f.write('')
is_login = True
return
else:
print('账户密码错误'.center(35,'-'))
def deco(func):
def wrapper(*args, **kwargs):
if is_login == False:
login()
if is_login == True:
res = func()
return res
else:
res = func(*args, **kwargs)
return res
return wrapper
@deco
def shopping():
'''购物'''
shopping_dict ={
'1' : 'tesla',
'2' : 'nike',
'3' : 'adidas',
'4' : 'buwawa'
}
# if is_login == True:
shopping_choice_dict = dict()
while True:
print(f'欢迎来到购物商城,请看你的购物列表{shopping_dict}')
shopping_choice = input('购物输入序列号购物,按q或Q即可退出购物').strip()
# if shopping_choice.isdigit() and 0 <= int(shopping_choice) <= 3:
if shopping_choice in shopping_dict:
# shopping_choice = int(shopping_choice)
print(f'你购买的是{shopping_dict[shopping_choice]}')
# 已买物品
# if shopping_dict[shopping_choice] in shopping_choice_dict:
# shopping_choice_dict[shopping_dict[shopping_choice]] += 1
# else:
# shopping_choice_dict[shopping_dict[shopping_choice]] = 1
if shopping_dict[shopping_choice] in shopping_choice_dict:
shopping_choice_dict[shopping_dict[shopping_choice]] += 1
else:
shopping_choice_dict[shopping_dict[shopping_choice]] = 1
elif shopping_choice == 'Q' or shopping_choice == 'q':
with open(f'{login_list[0]}shopping_history.txt', 'a', encoding='utf8') as fw:
fw.write(f'{login_list[0]}在{now_time}购买了{shopping_choice_dict}
')
print(f'{login_list[0]}你的商品清单{shopping_choice_dict}'.center(50,'-'))
print('购物结束'.center(40,'-'))
break
else:
print('输入有误'.center(40,'-'))
# shopping()
def quit():
print('谢谢惠顾,欢迎下次光临'.center(40,'*'))
exit()
@deco
def shop_list():
with open(f'{login_list[0]}shopping_history.txt', 'r', encoding='utf8') as fr:
data = fr.read()
print('aa')
print(data)
msg = {
'1' : register,
'2' : login,
'3' : shopping,
'4' : shop_list,
'5' : quit
}
msg_1 = {
1 : 'register',
2 : 'login',
3 : 'shopping',
4 : 'shop_list',
5 : 'quit'
}
while True:
msg_choice = input(f'请选择你需要的供能{msg_1}')
if msg_choice in msg:
msg[msg_choice]()
else:
print('输入有误')