前言
python中的变量的赋值以及函数参数的传递都是非常常见的用法,两个看似简单常见的语法,实际上可能会蕴含着巨大的玄机,稍不留意,可能会栽跟头,这也正是本文产生之缘由。。
python中变量的类型
一般来说,我们常见的python变量类型有以下几类:int、str、float、tuple、list、dict、set,并且按照“是否可变”可以将以上几类数据分类为可变变量和不可变变量:
可变变量: list、dict、set
不可变变量: int、str、float、tuple
下面我将就上述两种类型的变量,对python中的变量赋值及参数传递进行介绍。
一、变量的赋值
1.什么是变量??
对于这个问题,我是这样理解的:在实际的计算机中,每一个不同的数据都对应有实际的存储单元,而每个存储单元实际上也是由唯一的地地址给出的,所以变量和存储单元地址是具有对应关系的;
2.python中变量的赋值??
由于笔者是先学的C++,所以在写python的时候很多时候,也是将python中的变量与C++中变量的概念混淆!!!下面看我娓娓道来两者的区别,**真的很神奇**~
2.1 C++中的变量
学过C++的朋友可能知道,在C++中,每个不同的变量实际上是占据不同的地址空间的,例如下例子:
#include<iostream>
using namespace std;
int main(int argc, char *argv[])
{
int a = 10;
int b = 10;
cout<<"a的地址为:"<<&a<<endl;
cout<<"b的地址为:"<<&b<<endl;
return 0;
}
对应的输出为:
a的地址为:0x7ffc38e393dc
b的地址为:0x7ffc38e393d8
2.2 python中的变量
python中的变量不同于C++,我理解其是 依据取值进行单元分配的,如下例:
>>> a = 10
>>> b = 10
>>> c = 5
>>> print(id(a),id(b),id(c))
139736353391120 139736353391120 139736353390960
是不是很神奇!!!!
作为一个写C++出身的人,看到这个简直要一脸问号,这就是 世界上最好的语言py 么(bushi
简单总结一下的话 :
C++中是变量优先地址分配,python是值优先地址分配
直观点说就是:
C++是变量的值去找变量(上门服务,不是,上门赋值),且地址由变量决定
python是变量去找对应的值,且地址由值决定
3.python中可变变量和不可变变量指的是什么?
这里我的理解就是:对于指定存储单元地址下的对应数据类型的值,其是否可变。
看下例:
int类型数据--不可变变量:
>>> a = 8
>>> print(id(8))
139736353391056
>>> a = 10
>>> print(id(10))
139736353391120
list类型数据---可变变量
>>> c = [1,2,3]
>>> print(id(c))
139736231415552
>>> c[0] = 3
>>> print(id(c))
139736231415552
可以看到:
①对于不可变变量int,当我们将对应变量的值修改后,其对应的存储单元地址也发生改变,而原来存储单元地址下的值是没有改变的,也是无法改变的;
②而对于可变变量list:当修改该变量的内容时,其对应的存储单元地址并没有改变,还是原来的地址,说明其内容是可变的
这也是两者最大的区别!!!!
二、参数的传递
1.不可变类型变量参数的传递
对于不可变类型的变量,其参数的传递可以理解为 “值传递” 的过程——即只是将该变量对应的值传递给函数,函数中对应参数值的改变不会影响原变量,如下面的例子:
def f(a):
a = 10
return a
b = 19
c = f(b)
print(b)
print(c)
output:
19
10
可以看到,此时作为参数进行传递的b,其值并没有被修改
2.可变类型变量参数的传递
而对于可变类型的变量,其参数的传递可以理解为 C++中的 **“引用” **——即函数中该变量对应的值发生改变之后,原变量值也会改变:
def f(a):
a[0] = 10
return a
b = [1,2,3]
c = f(b)
print(b)
print(c)
output:
[10, 2, 3]
[10, 2, 3]
可以看到,此时作为参数传递进去的b,在函数执行完成过后,其值也被修改 !!!!!!!
【插一句:就是因为这个问题,我有个代码找了一天的bug。。。。】
如何避免可变类型变量在函数中被修改?
这时我们可以使用值拷贝的办法,如下面的例子:
def f(a):
a[0] = 10
return a
b = [1,2,3]
d = b[:]
c = f(d)
print(b)
print(c)
output:
[1, 2, 3]
[10, 2, 3]
通过利用 [:] 方法,实现对list的 值拷贝, 避免原list被修改,而对于dict类型数据,则可以按照下面的方法:
import copy
a = {1:1, 2:3, 3:4}
b = a
c = copy.deepcopy(a)
b[1] = 10
print(a)
print(b)
print(c)
output:
{1: 10, 2: 3, 3: 4}
{1: 10, 2: 3, 3: 4}
{1: 1, 2: 3, 3: 4}
可以看到,如果直接赋值,明显会导致其对原字典产生影响,但是通过deepcopy的方式,可以避免此影响。
实际上这里还涉及另外一个改变:深拷贝与浅拷贝, 大家感兴趣的可以去搜索一下,这里就不再过多介绍。
OK,以上就是全部内容,祝大家 睡觉好,吃饭香,代码无bug!!