【python】变量赋值

python初学,在给对象赋值时,发现当引用对象改变时,赋值对象也同时改变

对象传值

让我们先看一个栗子

    a = [0, [1, 2], 3]
    b = a
    print("a1",a)
    print("b1",b)
    a[0] = 8
    a[1][1] = 9
    print("a2", a)
    print("b2", b)

预想中print("a2", a) 输出的结果是b2 [0, [1, 2], 3]
但是,实际的输出结果是什么呢?

a1 [0, [1, 2], 3]
b1 [0, [1, 2], 3]
a2 [8, [1, 9], 3]
b2 [8, [1, 9], 3]

在 python 中赋值语句总是建立对象的引用值,而不是复制对象。因此,python 变量更像是指针,而不是数据存储区域

这里写图片描述

Python 没有「变量」,我们平时所说的变量其实只是「标签」,是引用

正确的复制嵌套元素的方法是进行「深复制」(deep copy),方法是

    import copy
    
    a = [0, [1, 2], 3]
    b = copy.deepcopy(a)
    print("a1",a)
    print("b1", b)
    a[0] = 8
    a[1][1] = 9
    print("a2",a)
    print("b2", b)

这样输出结果是

a1 [0, [1, 2], 3]
b1 [0, [1, 2], 3]
a2 [8, [1, 9], 3]
b2 [0, [1, 2], 3]

可变&不可变对象

在python中,对象分为两种:可变对象和不可变对象

不可变指的是值的不可变
对于不可变类型的变量,如果要更改变量,则会创建一个新值,把变量绑定到新值上,而旧值如果没有被引用就等待垃圾回收
可变类型数据对对象操作的时候,不需要再在其他地方申请内存,只需要在此对象后面连续申请(+/-)即可,也就是它的内存地址会保持不变,但区域会变长或者变短

可变对象:
list,set,dict

不可变对象:
int,float,long,str,tuple

看一下栗子

	a = 1 #将名字a与内存中值为1的内存绑定在一起
	a = 2 #将名字a与内存中值为2的内存绑定在一起,而不是修改原来a绑定的内存中的值,这时,内存中值为1的内存地址引用计数-1,当引用计数为0时,内存地址被回收
	b = a #变量b执行与a绑定的内存
	b = 3 #创建一个内存值为3的内存地址与变量名字b进行绑定。这是a还是指向值为2的内存地址。
	print(a,b) #2,3

具体的参数地址

str

a = 'xianglong.me'
print(id(a))   #140443303134352
a = '1saying.com'
print(id(a))   #140443303131776
# 重新赋值之后,变量a的内存地址已经变了
# 'xianglong.me'是str类型,不可变,所以赋值操作知识重新创建了str '1saying.com'对象,然后将变量a指向了它

list

a_list = [1, 2, 3]
print(id(a_list))   #140443302951680
a_list.append(4)
print(id(a_list))   #140443302951680
# list重新赋值之后,变量a_list的内存地址并未改变
# [1, 2, 3]是可变的,append操作只是改变了其value,变量a_list指向没有变

global关键字

s = 'foo'
d = {'a':1}
def f():
    s = 'bar'
    d['b'] = 2
f()
print s  # foo
print d  # {'a': 1, 'b': 2}

为什么修改字典d的值不用global关键字先声明呢?

这是因为,在s = 'bar'这句中,它是“有歧义的“,因为它既可以是表示引用全局变量s,也可以是创建一个新的局部变量
所以在python中,默认它的行为是创建局部变量,除非显式声明global,global定义的本地变量会变成其对应全局变量的一个别名,即是同一个变量
在d[‘b’]=2这句中,它是“明确的”,因为如果把d当作是局部变量的话,它会报KeyError,所以它只能是引用全局的d,故不需要多此一举显式声明global

但是如果是这样

d = {'a':1}
def f():
    d = {}
    d['b'] = 2
f()
print d  # {'a': 1}

d = {}这句,它是”有歧义的“了,所以它是创建了局部变量d,而不是引用全局变量d,所以d[‘b’]=2也是操作的局部变量

append/extend

# coding=utf-8
# 测试utf-8编码
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

list_a = []
def a():
    list_a = [1]      ## 语句1
a()
print list_a    # []

print "======================"

list_b = []
def b():
    list_b.append(1)    ## 语句2
b()
print list_b    # [1]

list_a = [1] 不能改变list_a的值,而list_b.append(1) 却可以,两种方法的差别在哪儿呢?

= 创建了局部变量,而 .append() 或者 .extend() 重用了全局变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

sysu_lluozh

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

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

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

打赏作者

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

抵扣说明:

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

余额充值