11_python基础—函数(引用、全局、局部变量)

本文详细介绍了Python中变量的引用概念,包括变量如何存储数据的内存地址,以及通过id()函数查看内存地址。接着,讨论了函数参数和返回值的引用传递。此外,还深入探讨了局部变量和全局变量的区别,包括它们的作用、生命周期和使用注意事项,特别是函数内部如何修改全局变量的值。文章最后提到了全局变量的定义位置和命名建议,强调了全局变量的使用应谨慎,以避免程序维护困难。

目标

  • 变量的引用
  • 可变和不可变类型
  • 局部变量和全局变量

一、 变量的引用

  • 变量 和 数据 都是保存在 内存 中的
  • Python函数 的 参数传递 以及 返回值 都是靠 引用 传递的

1.1 引用的概念

Python

  • 变量数据 是分开存储的
  • 数据 保存在内存中的一个位置
  • 变量 中保存着数据在内存中的地址
  • 变量记录数据的地址,就叫做 引用
  • 使用 id() 函数可以查看变量中保存数据所在的 内存地址

注意:如果变量已经被定义,当给一个变量赋值的时候,本质上是 修改了数据的引用

  • 变量 不再 对之前的数据引用
  • 变量 改为 对新赋值的数据引用

1.2 变量引用 的示例

Python 中,变量的名字类似于 便签纸 贴在 数据

  • 定义一个整数变量 a,并且赋值为 1
代码图示
a = 1004_a1tag
  • 将变量 a 赋值为 2
代码图示
a = 2image-20210505195846252
  • 定义一个整数变量 b,并且将变量 a 的值赋值给 b
代码图示
b = a006_ab2tag

变量 b 是第 2 个贴在数字 2 上的标签

1.3 函数的参数和返回值的传递

Python 中,函数的 实参/返回值 都是是靠 引用 来传递来的

def test(num):

    print("在函数内部 %d 对应的内存地址是 %d" % (num, id(num)))

    # 1> 定义一个字符串变量
    result = "hello"

    print("函数要返回数据的内存地址是 %d" % id(result))

    # 2> 将字符串变量返回,返回的是数据的引用,而不是数据本身
    return result

# 1. 定义一个数字的变量
a = 10

# 数据的地址本质上就是一个数字
print("a 变量保存数据的内存地址是 %d" % id(a))

# 2. 调用 test 函数,本质上传递的是实参保存数据的引用,而不是实参保存的数据!
# 注意:如果函数有返回值,但是没有定义变量接收
# 程序不会报错,但是无法获得返回结果
r = test(a)

print("%s 的内存地址是 %d" % (r, id(r)))

在这里插入图片描述

二、局部变量和全局变量

  • 局部变量 是在 函数内部 定义的变量,只能在函数内部使用
  • 全局变量 是在 函数外部定义 的变量(没有定义在某一个函数内),所有函数 内部 都可以使用这个变量

提示:在其他的开发语言中,大多 不推荐使用全局变量 —— 可变范围太大,导致程序不好维护!

2.1 局部变量

  • 局部变量 是在 函数内部 定义的变量,只能在函数内部使用
  • 函数执行结束后,函数内部的局部变量,会被系统回收
  • 不同的函数,可以定义相同的名字的局部变量,但是 彼此之间 不会产生影响
2.1.1 局部变量的作用
  • 在函数内部使用,临时 保存 函数内部需要使用的数据
def demo1():

    num = 10

    print(num)

    num = 20

    print("修改后 %d" % num)


def demo2():

    num = 100

    print(num)

demo1()
demo2()

print("over")

2.1.2 局部变量的生命周期
  • 所谓 生命周期 就是变量从 被创建被系统回收 的过程
  • 局部变量函数执行时 才会被创建
  • 函数执行结束后 局部变量 被系统回收
  • 局部变量在生命周期 内,可以用来存储 函数内部临时使用到的数据

2.2 全局变量

  • 全局变量 是在 函数外部定义 的变量,所有函数内部都可以使用这个变量
# 定义一个全局变量
num = 10


def demo1():

    print(num)


def demo2():

    print(num)

demo1()
demo2()

print("over")

注意:函数执行时,需要处理变量时 会:

  1. 首先 查找 函数内部 是否存在 指定名称 的局部变量如果有,直接使用
  2. 如果没有,查找 函数外部 是否存在 指定名称 的全局变量如果有,直接使用
  3. 如果还没有,程序报错!
1) 函数不能直接修改 全局变量的引用
  • 全局变量 是在 函数外部定义 的变量(没有定义在某一个函数内),所有函数 内部 都可以使用这个变量

提示:在其他的开发语言中,大多 不推荐使用全局变量 —— 可变范围太大,导致程序不好维护!

  • 在函数内部,可以 通过全局变量的引用获取对应的数据
  • 但是,不允许直接修改全局变量的引用 —— 使用赋值语句修改全局变量的值
num = 10


def demo1():

    print("demo1" + "-" * 50)

    # 如果使用赋值语句,在函数内部,只是定义了一个局部变量,不会修改到全局变量,只是变量名相同而已
    num = 100
    print(num)


def demo2():

    print("demo2" + "-" * 50)
    print(num)

demo1()
demo2()

print("over")

注意:只是在函数内部定义了一个局部变量而已,只是变量名相同 —— 在函数内部不能直接修改全局变量的值

2) 在函数内部修改全局变量的值(global关键字声明)
  • 如果在函数中需要修改全局变量,需要使用 global 进行声明
# 全局变量
num = 10


def demo1():

    # 希望修改全局变量的值 - 使用 global 声明一下变量即可
    # global 关键字会告诉解释器后面的变量是一个全局变量
    # 再使用赋值语句时,就不会创建局部变量
    global num

    num = 99

    print("demo1 ==> %d" % num)


def demo2():

    print("demo2 ==> %d" % num)


demo1()
demo2()

3) 全局变量定义的位置
  • 为了保证所有的函数都能够正确使用到全局变量,应该 将全局变量定义在其他函数的上方
# 注意:在开发时,应该把模块中的所有全局变量
# 定义在所有函数上方,就可以保证所有的函数
# 都能够正常的访问到每一个全局变量了
a = 10


def demo():
    print("%d" % a)
    print("%d" % b)
    print("%d" % c)

b = 20
demo()
c = 30

注意

  • 由于全局变量 c,是在调用函数之后,才定义的,在执行函数时,变量还没有定义,所以程序会报错!

代码结构示意图如下

4) 全局变量命名的建议
  • 为了避免局部变量和全局变量出现混淆,在定义全局变量时,有些公司会有一些开发要求,例如:
  • 全局变量名前应该增加 g_ 或者 gl_ 的前缀

提示:具体的要求格式,各公司要求可能会有些差异

<think>我们正在讨论Python局部变量全局变量的区别及使用方法。根据引用内容,我们可以总结以下几点: 1. **作用域差异**: - 全局变量:在函数外部定义,整个程序都可访问。 - 局部变量:在函数内部定义,仅在该函数内部有效。 2. **变量优先级**: - 当局部变量全局变量同名时,在函数内部优先使用局部变量(不会改变全局变量)。 3. **修改全局变量**: - 若需在函数内部修改全局变量,必须使用`global`关键字声明。 4. **使用场景**: - 全局变量适合存储程序级共享数据。 - 局部变量用于函数内部临时计算。 ### 示例解析 #### 示例1:局部变量不影响全局变量 ```python a = 4 # 全局变量 def b(): a = 8 # 局部变量(与全局变量a同名) print(a) # 输出局部变量a: 8 b() print(a) # 输出全局变量a: 4 ``` **输出**: ``` 8 4 ``` > 函数内部的`a`是独立于全局变量`a`的新局部变量[^1]。 #### 示例2:使用`global`修改全局变量 ```python a = 8 # 全局变量 def b(): global a # 声明使用全局变量a a = 2 # 修改全局变量 print(a) # 输出全局变量a: 2 b() print(a) # 输出全局变量a: 2(已被修改) ``` **输出**: ``` 2 2 ``` > 通过`global`关键字,函数内部操作直接作用于全局变量[^1][^3]。 ### 关键规则 1. **访问权限**: - 函数内部直接读取全局变量(无需声明): ```python x = 10 def read_global(): print(x) # 合法:输出10 ``` - 但修改全局变量必须使用`global`声明: ```python x = 10 def modify_global(): global x x = 20 # 合法修改 ``` 2. **变量隐藏**: - 在函数内部对未声明的变量赋会创建新的局部变量: ```python y = 5 def create_local(): y = 10 # 创建局部变量y,全局变量y不变 ``` 3. **嵌套作用域**: - 在嵌套函数中,若需修改外层非全局变量,需使用`nonlocal`关键字: ```python def outer(): z = 15 def inner(): nonlocal z # 引用外层函数的变量 z = 30 inner() print(z) # 输出30 ``` ### 最佳实践 - **避免滥用全局变量**:全局变量会增加代码耦合度,建议通过函数参数返回传递数据。 - **明确变量作用域**:使用`global`/`nonlocal`时需谨慎,确保理解其对变量的影响。 - **命名约定**:全局变量可使用大写或前缀(如`GLOBAL_VAR`)增强可读性。 ### 常见错误 ```python count = 0 def increment(): # 错误:未声明global,尝试修改全局变量 count += 1 # 引发UnboundLocalError increment() ``` **修正**: ```python count = 0 def increment(): global count count += 1 # 正确 ``` ### 总结 | **特性** | **全局变量** | **局部变量** | |------------------|-------------------|-------------------| | **定义位置** | 函数外部 | 函数内部 | | **作用域** | 整个程序 | 定义它的函数内部 | | **修改要求** | 需`global`声明 | 直接修改 | | **生命周期** | 程序运行期间 | 函数调用期间 | > 合理利用作用域规则能有效组织代码结构,避免命名冲突意外修改[^2][^4]。 §§相关问题§§ 1. 如何在Python的闭包中修改外部函数的变量? 2. Python的`nonlocal`关键字有哪些使用限制? 3. 全局变量在多线程环境下会引发哪些问题? 4. 如何通过类(Class)替代全局变量管理共享状态? [^1]: python中有关函数全局变量局部变量。在函数内部定义的a 是局部变量,当我们调用函数b的时候,函数内部打印的是局部变量函数外部打印的是全局变量a,并没有改变外部的全局变量。如果你想在函数内部改变全局变量,就要使用global关键字。 [^2]: python全局变量局部变量的区别_Python全局变量局部变量区别及用法分析。注:在方法内部的变量是在=号前面的,那肯定是局部变量。如果是第一次出现在=号后面的,那肯定是调用的全局变量全局变量可以在函数里面调用,局部变量只能在对应的函数里面调用,在该函数外面任何地方都无法被调用。 [^3]: python 局部变量全局变量。那如何在外部也能调用一个在局部里修改了的全局变量呢. 首先我们在外部定义一个全局变量a=None, 然后再fun()中声明 这个a是来自外部的a. 声明方式就是global a. 然后对这个外部的a修改后, 修改的效果会被施加到外部的a上。 [^4]: python局部变量全局变量区别。globalshowList#global代表引用全局变量,没办法,不写的话,showList就成局部变量了,赞吧 showList.append(1) showList.append(2) printshowList。</think># Python 函数局部变量全局变量的区别及使用方法 ## 1. 核心区别 ### 作用域范围 | **变量类型** | **作用域范围** | **生命周期** | |------------|---------------------|-------------------| | **全局变量** | 整个程序 | 程序运行期间 | | **局部变量** | 定义它的函数内部 | 函数执行期间 | ### 关键区别 - **全局变量**:在函数外部定义,整个程序都可访问 - **局部变量**:在函数内部定义,仅在该函数内部有效 - 当局部变量全局变量同名时,在函数内部**优先使用局部变量** ## 2. 基本行为演示 ### 示例1:局部变量不影响全局变量 ```python x = 10 # 全局变量 def modify(): x = 20 # 局部变量(与全局变量同名) print(f"函数内部: {x}") # 输出局部变量 modify() print(f"函数外部: {x}") # 输出全局变量 ``` **输出**: ``` 函数内部: 20 函数外部: 10 ``` > 函数内部的`x`是独立于全局变量`x`的新局部变量[^1] ### 示例2:函数访问全局变量(不修改) ```python count = 0 # 全局变量 def increment(): # 直接访问全局变量(只读) print(f"当前计数: {count}") increment() # 输出: 当前计数: 0 ``` > 函数内部可以直接读取全局变量,无需特殊声明[^2] ## 3. 修改全局变量:`global`关键字 ### 基本用法 ```python total = 100 # 全局变量 def update_total(): global total # 声明使用全局变量 total = 200 # 修改全局变量 print("修改前:", total) # 100 update_total() print("修改后:", total) # 200 ``` ### 实际应用场景 ```python USER_LIMIT = 100 # 全局配置 def adjust_limit(new_limit): global USER_LIMIT USER_LIMIT = new_limit print(f"用户限制已更新为: {USER_LIMIT}") adjust_limit(150) # 用户限制已更新为: 150 print("当前全局限制:", USER_LIMIT) # 150 ``` ## 4. 嵌套函数中的变量:`nonlocal`关键字 ### 解决闭包中的变量访问 ```python def outer(): counter = 0 # 闭包变量(非全局) def inner(): nonlocal counter # 声明使用外层变量 counter += 1 return counter return inner increment = outer() print(increment()) # 1 print(increment()) # 2 ``` > `nonlocal`用于访问嵌套函数外层(非全局)的变量[^3] ## 5. 最佳实践与注意事项 1. **避免全局变量滥用** - 过度使用全局变量会导致代码难以维护 - 建议将相关全局变量封装在类中 2. **命名规范** - 全局变量使用大写字母下划线:`MAX_CONNECTIONS = 10` - 局部变量使用小写字母下划线:`current_value = 5` 3. **安全修改模式** ```python config = {"timeout": 30} # 使用字典代替多个全局变量 def update_config(key, value): if key in config: config[key] = value else: print(f"无效配置项: {key}") update_config("timeout", 60) ``` 4. **函数参数优先** ```python # 推荐方式:通过参数传递 def calculate_area(radius): return 3.14 * radius ** 2 # 不推荐:依赖全局变量 radius = 5 def calculate_area(): return 3.14 * radius ** 2 ``` ## 6. 常见错误及解决方案 ### 错误1:未声明修改全局变量 ```python balance = 1000 def withdraw(amount): # 错误:尝试修改全局变量未声明 balance = balance - amount # UnboundLocalError withdraw(100) ``` **修复**: ```python def withdraw(amount): global balance balance -= amount ``` ### 错误2:误认为修改了全局变量 ```python items = [] def add_item(item): # 实际修改的是局部变量 items = [item] # 创建了新列表 add_item("apple") print(items) # 输出: [] (空列表) ``` **修复**: ```python def add_item(item): global items items.append(item) # 修改全局列表 ``` ## 总结 | **特性** | **全局变量** | **局部变量** | |------------------|-------------------|-------------------| | **定义位置** | 函数外部 | 函数内部 | | **访问范围** | 整个程序 | 定义它的函数内部 | | **修改要求** | 需`global`声明 | 直接修改 | | **生命周期** | 程序运行期间 | 函数调用期间 | | **内存效率** | 较低 | 较高 | > 合理利用作用域规则能有效组织代码结构,避免命名冲突意外修改[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少云清

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值