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 + "
"
                        # 写入文件
                        fp.write(strvar)
                        # 终止循环
                        sign = False
                        # 打印信息
                        print("注册成功~")
                        break
                    elif pwd2.upper() == "Q":
                        # sign = False
                        break
                        
                    else:
                        print("对不起,两次密码不一致~")
                    
    
注册(register.py)
# ### 登录
    # 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 + "
"
                                fp.write(strvar)
                            print("抱歉,您的账户已经被冻结~")                
                    times += 1 
        else:
            print("该用户不存在~")
        
登录(login.py)
ceshi1
ceshi2
ceshi3
ceshi4
黑名单(black.txt)
ceshi1:111
ceshi2:222
ceshi3:333
ceshi4:444
ceshi5:555
用户(user.txt)

 

原文地址:https://www.cnblogs.com/kongxiangqun/p/13337575.html