day11.函数的全局变量和局部变量
一、定义
""" 局部变量 : 在函数内部定义的变量(局部命名空间) 全局变量 : 在函数外部定义的或者使用global在函数内部定义(全局命名空间) 作用域: 作用的范围 局部变量作用域: 在函数的内部 全局变量作用域: 横跨整个文件 生命周期: 内置变量 > 全局变量 > 局部变量 """
1、局部变量
# 1.局部变量 def func(): # 定义局部变量 a = 5 # 获取局部变量 print(a) # 修改局部变量 a = 10 print(a) func() # print(a) error 不能再全局调用局部变量
2、全局变量
# 定义全局变量 b = 10 # 获取全局变量 print(b) # 修改全局变量 b = 20 def func(): # 可以在函数内部获取全局变量 print(b) func()
3、使用global在函数内部创建全局变量
def func(): global c c = 200 func() print(c)
4、使用global在函数内部修改全局变量
d = 300 def func(): global d d = 400 func() print(d)
""" 可以使用global 关键字在函数内部定义一个全局变量 也可以使用global关键字在函数内部修改一个全局变量 """
二、函数名的使用
def func(): print("我是func函数") return 1111 # 1.函数名是个特殊的变量,可以当做变量赋值 a = "你好" print(a) a = func a() # 函数可以像变量一样销毁 del a # a()
1、函数名可以作为容器类型数据的元素
def func1(): print("我是func1函数") def func2(): print("我是func2函数") def func3(): print("我是func3函数") lst = [func1,func2,func3] for i in lst: print(i) i() # func1() func2() func3()
2、函数名可以作为函数的参数
def func4(f): f() func4(func3)
3、函数名可作为函数的返回值
def func(f): return f res = func(func2) # f <=> func2 => res = func2() res() # ### __doc__ 或者 help查看文档 def eat_bigchang(something): """ 功能: 大肠刺身 参数: 肠子名字 返回值: 吃的状态 """ print("先把{}洗一洗".format(something)) print("找出肠子头放嘴里") print("嘬!!") return "吃完了,满意的放下肠子,擦擦嘴" res = eat_bigchang("猪肠子") print(res) help(eat_bigchang) res = eat_bigchang.__doc__ print(res)
三、函数的嵌套
""" 函数之间可以互相嵌套 外层的叫做外函数 内层的叫做内函数 """
def outer(): def inner(): print("我是inner函数") inner() outer()
1、 LEGB 原则
""" #找寻变量的调用顺序采用LEGB原则(即就近原则) B —— Builtin(Python);Python内置模块的命名空间 (内建作用域) G —— Global(module); 函数外部所在的命名空间 (全局作用域) E —— Enclosing function locals;外部嵌套函数的作用域(嵌套作用域) L —— Local(function);当前函数内的作用域 (局部作用域) 依据就近原则,从下往上 从里向外 依次寻找 """
四、nonlocal 修改局部变量
""" nonlocal遵循LEGB就近找变量原则 (1)找当前空间上一层的局部变量进行修改 (2)如果找不到,会继续向上寻找 (3)最后什么也没有,直接报错 """
1、找当前空间上一层的局部变量进行修改
def outer(): a = 100 def inner(): nonlocal a a = 200 print(a) inner() print(a) outer()
2、如果找不到,会继续向上寻找
def outer(): a = 100 def inner(): def smaller(): nonlocal a a = 400 print(a) smaller() print(a) inner() print(a) outer()
注意点:nonlocal只能修改局部变量
""" a = 100 def outer(): def inner(): def smaller(): nonlocal a a = 400 print(a) smaller() print(a) inner() print(a) outer() """
3、不使用nonlocal 修改局部变量
def func(): lst = [1,2,3,4] def inner(): lst[-1] = 10 inner() print(lst) func()
五、locals 和 globals
locals 获取当前作用域中所有变量
""" locals 如果在全局,调用locals之后,获取的是打印之前的所有变量,返回字典,全局空间作用域 locals 如果在局部,调用locals之后,获取的是调用之前的所有变量,返回字典,局部空间作用域 """
例1、打印res 之前的所有变量
""" def func(): ff = 123 a = 1 b = 2 res = locals() c = 3 print(res) d = 4 """ # 'a': 1, 'b': 2, 'res': {...}, 'c': 3
例2、调用之前的所有变量
a1 = 10 def func(): a = 1 b = 2 res = locals() c = 3 print(res) d = 4 a2 = 20 func() a3 = 30 # 'a1': 10, 'a2': 20
1、globals 只获取全局空间中所有变量
""" globals 如果在全局,调用globals之后,获取的是打印之前的所有变量,返回字典,全局空间作用域 globals 如果在局部,调用globals之后,获取的是调用之前的所有变量,返回字典,全局空间作用域 """
例1、
def func(): ff = 123 a = 1 b = 2 res = globals() c = 3 print(res) d = 4 # 'a': 1, 'b': 2, 'res': {...}, 'c': 3
例2、
a1 = 10 def func(): a = 1 b = 2 res = globals() c = 3 print(res) d = 4 a2 = 20 func() # globals a3 = 30 # 'a1': 10, 'func': <function func at 0x00000289E7B9C1E0>, 'a2': 20
2、动态批量创建全局变量
2.1、用字符串定义全局变量
dic = globals() print(dic) # 返回的是系统的字典 # 在全局的字典当中,通过添加键值对,自动创建全局变量 # 对应的键时变量名,对应的值是变量指向的值 dic["name"] = "aa" print(name)
2.2、批量定义全局变量
def func(): dic = globals() # 通过在全局系统字典当中,添加键值对,批量创建变量 for i in range(1,6): # "a%d" % (1) => "a1" "a%d" % (2) => "a2" dic["a%d" % (i)] = i # 1~5 func()
""" "a%d" % (1) => a1 "a%d" % (2) => a2 "a%d" % (3) => a3 "a%d" % (4) => a4 "a%d" % (5) => a5 """
六、登录注册练习
写一个登陆注册小程序 登录: # 1.账户密码会预先记录在文件中 # 2.输入账号密码:如果都正确,登录成功 # 3.如果用户登录时进行三次校验,都不对,记录黑名单文件中 # 4.如果是黑名单的用户,禁止下次再次登录 注册: # 1.检测两次密码如果相同,确认注册成功 # 2.检测两次密码如果不同,提示两次密码不一致 # 3.用户名不能重复
# 注册: # 1.检测两次密码如果相同,确认注册成功 # 2.检测两次密码如果不同,提示两次密码不一致 # 3.用户名不能重复 # accountlst存放所有账号 accountlst = [] sign = True with open("user.txt",mode="a+",encoding="utf-8") as fp: while sign: # 输入用户名 username = input("请输入要注册的用户名:") if username == "" or " " in username: print("对不起,该名字含有非法字符") else: # 把数据从文件当中获取 fp.seek(0) lst = fp.readlines() for i in lst: account = i.strip().split(":")[0] accountlst.append(account) print(accountlst) # 判断该名字是否已经存在 if username in accountlst: print("抱歉,改名字已经使用~") else: # 检测密码 pwd = input("请输入您的密码") while True: pwd2 = input("请确认您的密码,按q退出~") # 如果密码相同 if pwd == pwd2: # 拼接字符串 strvar = username + ":" + pwd + "\n" # 写入文件 fp.write(strvar) # 终止循环 sign = False # 打印信息 print("注册成功~") break elif pwd2.upper() == "Q": # sign = False break else: print("对不起,两次密码不一致~")
# ### 登录 # 1.账户密码会预先记录在文件中 # 2.输入账号密码:如果都正确,登录成功 # 3.如果用户登录时进行三次校验,都不对,记录黑名单文件中 # 4.如果是黑名单的用户,禁止下次再次登录 # 存账户 accountlst = [] # 存密码 pwdlst = [] # 存黑名单 blacklst = [] sign = True while sign: username = input("请输入您的用户名:") # 获取文件当中的账号和密码 with open("user.txt",mode="a+",encoding="utf-8") as fp: fp.seek(0) lst = fp.readlines() for i in lst: user,pwd = i.strip().split(":") # print(username,password) accountlst.append(user) pwdlst.append(pwd) # print(accountlst) # print(pwdlst) # 判断该用户是否存在 if username in accountlst: # 判断当前用户是否是黑名单中的用户 with open("black.txt",mode="a+",encoding="utf-8") as fp: fp.seek(0) lst = fp.readlines() for i in lst: blacklst.append(i.strip()) # print(blacklst) # print(username) if username in blacklst: print("抱歉,该用户已经被冻结了") else: # 如何找到该账户对应的密码呢? num = accountlst.index(username) pwd = pwdlst[num] # print(num,pwd) """""" # 判断用户输入的密码是否正确 times = 1 while times <= 3: pwd2 = input("请输入您的密码") # 输入成功情况下,终止循环,程序结束 if pwd == pwd2: print("登录成功") sign = False break else: # 剩余的次数 = 总次数 - 使用次数 print("你还剩下%s次机会" % (3 - times)) # 如果用掉了所有的次数,直接加入黑名单,防止下次登录 if times == 3: with open("black.txt",mode="a+",encoding="utf-8") as fp: strvar = username + "\n" fp.write(strvar) print("抱歉,您的账户已经被冻结~") times += 1 else: print("该用户不存在~")
ceshi1
ceshi2
ceshi3
ceshi4
ceshi1:111 ceshi2:222 ceshi3:333 ceshi4:444 ceshi5:555