python对象的引用

Python中万物皆对象,变量是对象,方法是对象………

Python对象的引用分为浅拷贝和深拷贝以及类的方法引用

一.引用的理解:其实就是对象的指针

  1. 引用是内存中真实对象的指针,表示为变量名或内存地址

  2. 每个对象至少存在1个引用,id()函数用于获取引用

  3. 在传递参数和赋值时,python传递对象的引用,而不是复制对象

举例:对象的指针是引用

  ls = [1,2,3,4,5]
  lt = ls
  print(id(ls))
  print(id(lt))
  
 列表类被实例化,给出了ls,而ls赋值给lt并没有真正实例化,而仅仅是将指针复制了一份.

二.Python内部机制对引用的处理:

  1. 不可变对象:immutable解释器为相同值维护尽量少的内存区域

  2. 可变对象:mutable解释器为每个对象维护不同内存区域

(1).对不可变对象的引用:

举例:

  a = 10
  b = a
  c = 10
  print(id(a))
  print(id(b))
  print(id(c))

结果:

在这里插入图片描述

Python为相同的值开辟了同一块内存区域,除了整数类似的还有字符串等,当然浮点数也可以.但是有一种情况除外.

  a = "as"
  b = a
  c = "as"
  d = "a"
  e = "s"
  f = d+e
  print(id(a))
  print(id(b))
  print(id(c))
  print(id(d))
  print(id(e))
  print(id(f))

结果:

在这里插入图片描述

虽然f与a相等,但是python不会对未来的结果进行计算,他会对结果新开辟一块空间.所以相同的结果可能有不同的内存地址.

(2).对可变对象的引用

可变对象类型,只要被创建就会独立的分配内存空间

举例:

  a = []
  b = a
  c = []
  print(id(a))
  print(id(b))
  print(id(c))

结果:
在这里插入图片描述

对于引用,只要有一个引用向内存空间做了修改,另外一个引用就会发生变化.

例子:

  a = []
  b = a
  b.append(1)
  print(a,id(a))
  print(b,id(b))

结果:

在这里插入图片描述

三.引用的理解

1.导致引用+1的情况:

 对象被创建:d = class()

 对象被引用:a = d

 对象被作为函数或方法的参数:sys.get(d)

 对象被作为一个容器中的元素:ls = [d]

2.导致引用-1的情况:

对象被删除:del d

对象的名字被赋予新的对象:d = 123

对象离开作用域:foo()函数的局部变量count

对象所在容器被删除: del ls

四.对象的拷贝

拷贝分为浅拷贝和深拷贝

拷贝:复制一个对象为新的对象,内存空间有”变化”

浅拷贝:仅复制最顶层对象的拷贝方式,默认拷贝方式

深拷贝:迭代复制所有对象的拷贝方式

浅拷贝

例子:

  a =
  ["sss",[886]]
  b = a.copy()
  c = a[:]
  d = list(a)
  print("a",id(a),a)
  print("b",id(b),b)
  print("c",id(c),c)
  print("d",id(d),d)
  
 

结果:

在这里插入图片描述

也就是说,经过拷贝,切片,类型定义,内存位置都发生了变化.注意,这里如果是整数类型,或者说是不可变类型,类型重定义为同种类型,内存地址不发生变化.

copy一般是对可变数据类型,list和array中有copy

上述程序中,列表中的元素的地址都相同,也就是说列表被拷贝了,但元素没有被拷贝.因为上述对象被作为一个容器中的元素:ls = [d]引用+1,故ls包含的实际上是一个指向字符串"sss"的指针和一个指向列表[886]的指针.实际上复制的是指针,或者说引用,并没有复制每个元素的内存空间.这就是浅拷贝.带来的问题是这些浅拷贝中对一个其中可变元素进行改变,其他的浅拷贝中都发生了变化.

  a = [1,2,[3]]
  b = a.copy()
  b[-1].append(2)
  print(id(a),a)
  print(id(b),b)
  
  a = [1,2,[3]]
  b = a.copy()
  b.append(2)
  print(id(a),a)
  print(id(b),b)
  

左边全都发生变化,因为拷贝的里面的指针中的值生了变化,右边只有b发生了变化,因为此时改变的只是列表中的引用.细细体会!

深拷贝

(1).Python不默认支持深拷贝.

采用copy库的deepcopy()方法

迭代拷贝对象内各个层次对象,完全新开辟内存建立对象

深拷贝仅针对可变类型,不可变类型无需创建新对象,也就是说拷贝对象元素中包含不可变类型,那么深拷贝后,该不可变类型内存地址依旧不变.

(2).与浅拷贝的区别:

浅拷贝:仅复制最顶层对象的拷贝方式,默认拷贝方式

深拷贝:迭代复制所有对象的拷贝方式,采用copy库的deepcopy()

一般深拷贝都与可变类型关联

五.类的方法引用

定义方式:def <实例方法名>(self,<参数列表>)

实例方法名也是一种引用,即对方法本身的引用

当方法被引用时,方法(即函数)将产生一个对象:方法对象

两个例子类方法的引用:

<对象名>.<方法> 是对一个方法的引用,注:方法后面没有方法参数

  class Deo:
      def __init__(self,name):
          self.name = name
      def
  lucky(self,salt= 0):
          s = salt**2
          return s
  dc1 =
  Deo("laowang")
  lucky = dc1.lucky
  #对象名.方法名就是这个方法的引用
  print(Deo.lucky(dc1,10))
  print(dc1.lucky(10))
  print(lucky(10))
  a = 


[1,2,3]
  b = a.copy()
  b.append(2)
  c = a.append#方法引用
  c(4)
  print(id(a),a)
  print(id(b),b)

结果:
在这里插入图片描述
在这里插入图片描述

注:<对象名>.<方法名>(方法参数)

 等价于

<类名>.<方法名>(<对象名>,方法参数)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值