Python变量机制深度解析:引用、可变性及作用域实战

苏见山
苏见山
发布时间:2026-10-12 | 2人浏览过
原创

本文深入解析Python变量核心机制,涵盖变量与数据的内存分离存储原理、引用传递特性。详细对比int、str等不可变类型与list、dict等可变类型的内存行为差异,并解析局部变量生命周期及全局变量在函数中的访问与修改规则,包括global关键字的正确使用及命名规范建议。

本文详细介绍Python中变量的基础用法及进阶特性,旨在帮助开发者深入理解其内部机制,供参考学习。

  • 变量的引用机制
  • 可变类型与不可变类型的区别
  • 局部变量与全局变量的作用域规则
  • 变量与数据在内存中的存储关系
  • 函数参数传递与返回值均基于引用传递

1.1 引用的基本概念

在Python语言中,

  • 变量名与数据对象是分开存储的
  • 实际的数据对象存储在内存的特定位置
  • 变量名中保存的是指向该数据对象的内存地址
  • 这种记录数据内存地址的行为被称为“引用”
  • 可以通过调用id()函数查看变量所指向数据的内存地址

需要注意的是,若变量已存在,再次赋值本质上是修改了该变量的引用指向

  • 变量将不再指向之前的数据对象
  • 变量将改为指向新赋值的数据对象

1.2 变量引用的具体示例

在Python中,变量名类似于贴在数据对象上的标签

  • 定义一个整数变量a并赋值为1 将变量a重新赋值为2 定义整数变量b,并将变量a的值赋给b 此时变量b成为指向数字2的第二个标签

1.3 函数参数与返回值的传递机制

在Python中,函数的实参传递及返回值均通过引用方式进行

def test(num):

  print("-" * 50)
  print("%d 在函数内的内存地址是 %x" % (num, id(num)))

  result = 100

  print("返回值 %d 在内存中的地址是 %x" % (result, id(result)))
  print("-" * 50)

  return result

a = 10
print("调用函数前 内存地址是 %x" % id(a))

r = test(a)

print("调用函数后 实参内存地址是 %x" % id(a))
print("调用函数后 返回值内存地址是 %x" % id(r))

  • 不可变类型,内存中的数据不允许被修改:
    • 不可变类型包括:int、bool、float、complex、long(仅Python 2.x)
    • 字符串类型 str
    • 元组类型 tuple
  • 可变类型,内存中的数据可以被修改:
    • 列表类型 list
    • 字典类型 dict
a = 1
a = "hello"
a = [1, 2, 3]
a = [3, 2, 1]
demo_list = [1, 2, 3]

print("定义列表后的内存地址 %d" % id(demo_list))

demo_list.append(999)
demo_list.pop(0)
demo_list.remove(2)
demo_list[0] = 10

print("修改数据后的内存地址 %d" % id(demo_list))

demo_dict = {"name": "小明"}

print("定义字典后的内存地址 %d" % id(demo_dict))

demo_dict["age"] = 18
demo_dict.pop("name")
demo_dict["name"] = "老王"

print("修改数据后的内存地址 %d" % id(demo_dict))

注意:字典的键(key)只能使用不可变类型的数据

注意事项

  1. 可变类型的数据修改是通过调用特定方法实现的
  2. 若给可变类型变量赋值新数据,其引用会指向新数据
    • 变量不再指向之前的数据对象
    • 变量改为指向新赋值的数据对象

哈希 (hash)

  • Python内置有一个名为hash(o)的函数
    • 接收一个不可变类型的数据作为参数
    • 返回结果为一个整数
  • 哈希是一种算法,用于提取数据的特征码(指纹)
    • 相同的内容会产生相同的哈希结果
    • 不同的内容会产生不同的哈希结果
  • 在Python中,设置字典键值对时,会首先对key进行hash计算,以决定如何在内存中存储字典数据,从而方便后续对字典进行增、删、改、查操作
    • 字典键值对中的key必须为不可变类型数据
    • 字典键值对中的value可以是任意类型的数据
  • 局部变量是在函数内部定义的变量,仅限函数内部访问
  • 全局变量是在函数外部定义的变量(未定义在特定函数内),所有函数内部均可使用

提示:在其他开发语言中,通常不推荐使用全局变量,因其作用域过大可能导致程序难以维护

3.1 局部变量详解

  • 局部变量是在函数内部定义的变量,仅限函数内部访问
  • 函数执行完毕后,系统会回收函数内部的局部变量
  • 不同函数可定义同名局部变量,彼此互不影响

局部变量的主要作用

  • 在函数内部临时保存所需使用的数据
def demo1():

  num = 10

  print(num)

  num = 20

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


def demo2():

  num = 100

  print(num)

demo1()
demo2()

print("over")

局部变量的生命周期

  • 生命周期指变量从创建到被系统回收的过程
  • 局部变量仅在函数执行时被创建
  • 函数执行结束后,局部变量被系统回收
  • 在生命周期内,局部变量可用于存储函数内部临时使用的数据

3.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关键字进行声明
num = 10


def demo1():

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

  # global 关键字,告诉 Python 解释器 num 是一个全局变量
  global num
  # 只是定义了一个局部变量,不会修改到全局变量,只是变量名相同而已
  num = 100
  print(num)


def demo2():

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

demo1()
demo2()

print("over")

3) 全局变量的定义位置

  • 为确保所有函数能正确使用全局变量,应将全局变量定义在其他函数的上方
a = 10


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

b = 20
demo()
c = 30

注意事项

  • 若全局变量c在调用函数之后才定义,执行函数时变量尚未定义,程序将报错

代码结构示意图如下 4) 全局变量的命名建议

  • 为避免局部变量与全局变量混淆,部分公司制定了开发规范,例如:
  • 全局变量名前建议增加g_或gl_前缀

提示:具体格式要求各公司可能有所不同

关于Python相关内容感兴趣的读者可查看本站专题:《Python函数使用技巧总结》、《Python面向对象程序设计入门与进阶教程》、《Python数据结构与算法教程》、《Python字符串操作技巧汇总》、《Python编码操作技巧总结》及《Python入门与进阶经典教程》

希望本文所述内容对大家学习Python程序设计有所帮助。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表