Python入门课程5—对象引用、可变性

一、对象引用

变量类似于便利贴,为所引用的对象增加一个别名。
例如:数字1是一个int对象,a=1即“把变量a分配给1”。因为对象在赋值之前就创建了,一个赋值语句中,语句右边先执行,再进行把变量分配给对象的操作。

二、相等性(== 和 is)

1、相等性
a = {'name':'qiqi','born':1994}
b = {'name':'qiqi','born':1994}
c = a
>>> id (a)
>>> 2362294492256
>>> id (b)
>>> 2362295102848
>>> id (c)
>>> 2362294492256

在这个例子中,变量a和c绑定了同一个对象,变量b绑定了另一个具有相同内容的对象。
a 和 c 是“相等”的,c 是 a 引用的对象的另一个别名;a和b是不相等的。

2、== 和 is

每个变量都有标识类型
对象一旦创建,它的标识绝不会变(可以把标识理解为对象在内存中的地址)

is运算符:比较两个对象的标识
==运算符:比较两个对象的(通过__eq__函数定义,可以被重载)

注意:
1、在变量和单例值之间比较时,应该使用is,如x is None
2、is== 速度快,因为它不能重载,Python不用寻找并调用特殊方法。且a == b等同于a.__eq__(b),在大型集合或嵌套层级深的结构时,可能涉及大量处理工作。

三、相对不可变性

以元组为例,元组内保存的是对象的引用,如果引用的元素是可变的,即使元祖不可变,元素依然可变。即,元祖的不可变性其实指的是tuple数据结构的物理内容(即保存的引用)不可变

四、复制(浅复制和深复制)

1、浅复制
l1 = [3,[55,44],(7,8,9)]
l2 = list(l1)
l3 = l1[:]

其中,构造方法(l2 = list(l1))和l1[:]做的都是浅复制,即只复制了最外层的容器,副本l2、l3共享了内部对象的引用(副本中的元素是源容器中元素的引用)。
如果所有元素都不可变,那么这样没有问题,还能节省内存。但如果元素是可变的,可能会导致意想不到的问题。

2、深复制

深复制,即副本不共享内部对象的引用。
可以通过copy模块提供的deepcopy函数实现
注:copy.copy()对对象做浅复制;copy.deepcopy()对对象做深复制

五、当函数的参数是引用时

1、共享传参

python支持的参数传递模式是共享传参.
即:函数的各个形参获得实参中各个引用的副本。也就是说,函数内部的形参是实参的别名。

举例说明:

def f(a,b):
	a += b
	return a 

>>> x= 1
>>> y =2
>>> f(x,y)
3
>>> x,y
(1,2)

在上例中,函数f的形参a获取实参x的副本(即1),形参b获取实参y的副本(即2)。然后进行运算1 + 2 =3,并将形参a分配给了新的对象 3。
在此过程中,由于x引用的对象是不可变对象,x并未改变,仍引用对象1;a变了,引用对象3。此时x和a已不引用同一对象了。

def f(a,b):
	a += b
	return a 

>>> x = [1,2]
>>> y =[3,4]
>>> f(x,y)
[1,2,3,4]
>>> x,y
([1,2,3,4],[3,4])

在上例中,由于x引用的是列表,是可变的,于是在形参a共享参数进行运算时,改变了x引用对象的值,没有把a分配给新的对象。
此时x和a仍引用同一对象,但对象的值改变了。

2、不要使用可变类型作为参数的默认值

当函数的参数的默认值是可变对象时,每次调用函数都可能改变默认值,于是下一次调用函数时,默认值就不是我们想要的默认值了。
举例说明,如:

class A
	def  __ init__ (self,l = None):
		if list is None:
			self.xxx = []
		else:
			self.xxx =list(l)

“优化”为

def  __ init__ (self,list=[]):
	self.xxx =list

以上“优化”看起来可以一次if判断,实际上这个举动会让我们陷入麻烦。
当进行

a = A()  		#此时,a引用的是__init__函数里,形参list的默认值[]
a
>>>[]
a.append('hh')		 #a引用的是__init__函数里,形参list的默认值[]修改成了['hh']
a
>>>['hh']
b = A()			#于是下一次实例化A类时,b的默认值成了['hh']
b
>>>['hh']
3、防御可变参数

当定义的函数接受可变参数,就应该谨慎考虑调用方是否期望修改传入的参数.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值