python中的传参(传副本)、变量赋值操作、传引用和全局变量与局部变量

文章目录

  • 前言
    • !!!!!!!!!!!!看本博客前,千万先看这篇博客[内存模型](https://blog.csdn.net/smalltorch/article/details/139722852)
  • 一【事实1】:python传参都是 ---- 传引用
  • 二 python中的变量赋值操作理解(很重要)
    • 1 Python的赋值机制
      • (1) 直接赋值
      • (2) 改变引用
      • (3) 赋值操作的细节
      • (4) 可变对象与不可变对象
      • (5) 赋值操作是否创建新对象?
      • 小结
    • 2 一个重要帮助理解的整数对象例子
      • (1)代码分析
      • (2)详细解答
      • (3)深入理解
      • 小结
    • 3 一个重要帮助理解的列表对象例子
      • (1)列表及其元素的引用
        • 列表初始化
        • 列表引用的赋值
        • 修改列表中的元素
        • 列表的内容变化
      • (2)关键点总结
      • (3)更详细的内部机制
      • 小结
  • 三、全局变量与局部变量
  • 四、python函数的传参
    • 1 实参与形参
    • 2 可变数据与不可变数据
    • 3 传值(假的传值)与传引用
      • (1)传值(本质上还是传引用---由于python不可变数据的特性就变成和C语言里面传值的效果一样了)
        • 示例一:对于不可变数据类型,如果你将一个变量作为参数传递给函数,在函数内部对该参数进行修改不会影响到函数外部的原始变量。
        • 示例2:不要与有返回值混淆
        • 示例3:如果我非要让示例1输出4呢,这就要用全局变量
          • 方法1:在函数里面声明是全局变量(用global)
          • 方法二:类里面用self属性在函数里面定义变量(相当于也是在函数里面声明了是全局变量)
      • (2)传引用
    • 4 传值与传引用本质统一(重要)
      • (1)函数内部进行赋值操作会发生什么
      • (2)修改操作就舒服多了,随便造(当然别赋值哈哈哈)
  • 总结


前言

!!!!!!!!!!!!看本博客前,千万先看这篇博客内存模型

【注】下面的一切的一切看完上面那篇内存模型博客才会理解通透,不然还是强行记忆没什么屁用。

在python编程中函数的传参需要特别注意,有时会忘记,在这里写篇文章记录一下。每次查资料发现很多都是没有说明白的,作者自己都是稀里糊涂的。因此直接自己在这里写一篇注意一下。
在进行下面内容讲解之前需要先明白几个事实:

一【事实1】:python传参都是 ---- 传引用

python中所有的传参传的都是对象的引用(地址),只是由于可变数据类型和不可变数据类型的特性才导致了不同的效果。
真正的 传值与传引用解释(java):
(1)传值:传对象的副本,意味着传进去的东西和原始的没有任何关系,副本怎么变都不会影响到原始对象。
(2)传引用(传地址):很显然,传地址就是传同一个东西,修改另一个就会影响到另一个
python中都是传引用怎么解释:

a = 1
b = a
print(id(a), id(b))         # 2542304520496 2542304520496
a = 1

def f(x):
    print(id(x))
print(id(a))      # 2542304520496      
f(a)              # 2542304520496

看完两个例子是不是都是传引用,哈哈。
那为什么不可变数据也是传引用,为什么会产生内部修改不影响外部呢?传引用不应该都是一起变吗?
解答:这是python的中不可变数据类型的特性,由于不可变的特性在,修改其中一个由于不可变,只能被迫创建一个新的对象,赋值给变量。这就不可变的含义所在;慢慢看下面以及前面那篇内存模型结构的博客就明白了。

二 python中的变量赋值操作理解(很重要)

在Python中,赋值操作有多种形式,而它们在不同的上下文中可能有不同的效果。为了更好地理解Python的赋值机制,我们需要明确以下几个概念:

  1. 对象和引用:Python中的一切都是对象,变量只是这些对象的引用。
  2. 赋值操作的不同效果:赋值操作不仅仅是创建新对象,更多的是将引用绑定到对象上。
  3. 可变性和不可变性:对象的可变性决定了赋值和操作对对象本身和引用的影响。

1 Python的赋值机制

(1) 直接赋值

a = 10
b = a
  • 含义a = 10 创建一个整数对象 10 并将 a 绑定到它。b = a 使得 b 引用同一个对象 10
    只要执行 a = 10这行代码 a就会有一个id地址指向对象10
  • 结果ab 都引用相同的对象 10

在这个情况下,赋值操作 b = a 只是将 b 绑定到 a 当前引用的对象,并没有创建新的对象。此时,ab 的地址(引用)是相同的。

print(id(a), id(b))  # 输出相同的地址

(2) 改变引用

b += 1
  • 含义b += 1 实际上是 b = b + 1 的简写。由于整数是不可变的,b + 1 计算结果为 11,Python创建了一个新的整数对象 11,并将 b 绑定到这个新的对象。
  • 结果a 仍然引用 10,而 b 现在引用 11

此时,ab 的引用已经不同,因为 b 被重新绑定到了一个新创建的对象 11

print(id(a), id(b))  # 输出不同的地址

(3) 赋值操作的细节

在Python中,赋值操作有以下几种情形:

  • 简单赋值

    x = y
    

    这种操作将变量 x 绑定到 y 引用的对象。xy 最终引用相同的对象。

  • 增强赋值(例如 +=-= 等):

    x += 1
    

    对于不可变对象,这会创建一个新对象,并将 x 绑定到新对象。对于可变对象(如列表),则会在原地修改对象。

  • 多重赋值

    x, y = 1, 2
    

    这种操作是同时将 x 绑定到 1y 绑定到 2

  • 链式赋值

    x = y = 10
    

    这种操作将 xy 都绑定到相同的对象 10

  • 序列解包

    a, b = [1, 2]
    

    这种操作将列表 [1, 2] 中的元素分别绑定到 ab

(4) 可变对象与不可变对象

对象的可变性影响了赋值操作后的结果:

  • 不可变对象:如 intfloatstrtuple 等,一旦创建,其值就不能更改。对于不可变对象,任何改变其值的操作都会创建一个新对象。

    x = 10
    y = x
    y += 1  # 创建了新的整数对象 11
    print(x)  # 输出 10
    print(y)  # 输出 11
    
  • 可变对象:如 listdictset 等,其内容是可以修改的。对于可变对象,修改内容不会改变对象的引用。

    x = [1, 2, 3]
    y = x
    y.append(4)  # 修改了 x 引用的对象
    print(x)  # 输出 [1, 2, 3, 4]
    print(y)  # 输出 [1, 2, 3, 4]
    

在这个例子中,xy 最初都引用同一个列表对象。对 y 的修改反映在 x 上,因为它们引用的是同一个对象。

你可能感兴趣的:(python,基础(语法以及多线程等操作),python,开发语言)