欢迎加入QQ讨论群258996829
麦子学院 头像
苹果6袋
6
麦子学院

python对象的可变类型与不可变类型

发布时间:2017-09-18 15:35  回复:0  查看:3022   最后回复:2017-09-18 15:35  
本文和大家分享的主要是python 对象的可变类型与不可变类型相关内容,一起来看看吧,希望对大家 学习python有所帮助。
  python 对象对于修改这个行为,大家的操作方式都是不一样的。有些对象是可变类型,所以他就可以直接修改。其它的都是不可变类型,那我们要修改他时怎么办呢,这个时候就新生成的一个对象,然后将变量名指向这个新对象,修改动作就完成了。关于可变类型与不可变类型的一个特点,我们可以先看看一段奇怪的代码
   In [1]: a = 'a'
   In [2]: b = 'a'
   In [3]: a  is b
  Out[3]: True
   In [4]: a == b
  Out[4]: True
   In [5]: c = [1]
   In [6]: d = [1]
   In [7]: c  is d
  Out[7]: False
   In [8]: c == d
  Out[8]: True
  你有没有觉得,a b  明明都是不同的对象,但是使用 a is b  的时候 竟然返回了 true  ,这里面就会深入到对象的别名,标识与相等性,先说回到可变类型与不可变类型
   分类
   不可变类型
  · int
  · float
  · decimal
  · complex
  · bool
  · string
  · tuple
  · range
  · frozenset
  · bytes
   可变类型
  · list
  · dict
  · set
  · bytearray
  · user-defined classes (unless specifically made immutable)
  有个简单的方式来区分这些类型,类似的容器类型的数据就是可变类型(list,set,dict)— 我们就想像一个容器可以不停的注入内容,其它的基本都是不可变的类型,这里有几个特殊的
  ·  元组  tuple
  · frozenset
  · str
   区分类型?有这个必要吗?
  当然是显然的,虽然我们在实际的工程环节都会围绕整体的业务问题,很少去了解底层的原理,但是我们一旦涉及到优化,涉及到底层的时候就很有必要了解技术细节。举个例子,如何高效的拼接字符串,我想下面的代码大部分人都写过,包括我
   In [13]: str_build = '' In [14]:  for p  in 'aaabbbccc':
  ...:     str_build = str_build + p
  事实上,这样的效率并不是很高。如上所言,我们知道str  是不可变类型,我们在拼接字符串的时候,实际上是生成了一个新的对象,然后在变量名指向他,随着拼接的次数越来越多,我们生成对象的操作次数也会越来越多,这样就很没有这个必要 (C#  里面的 StringBuilder  就是为了解决字符串拼接的 ) ,那有效率的写法是怎样的呢
  builder_list = [] for data in container:
  builder_list. append(str(data))"". join(builder_list)
  ### Another way  is  to use  a  list comprehension"". join([str(data)  for data in container])
  ### or use the  map  function"". join( map(str, container))
  我们通过使用列表,可以轻松的在本身对象的基础上修改内容,不会生成新对象来处理操作,这样就会节省内存
  另外的一个我们会遇到关于可变类型的一个坑
   def  my_function(param=[]):
  param.append("thing")
   return param
  my_function() # returns ["thing"]
  my_function() # returns ["thing", "thing"]
  你会不会觉得,我去,不管我调用多少次,这丫不是应该就返回一个[‘thing’] 回来吗?但是事实上你也看到了,因为可变对象一直都会引用同一段内容,我们在操作列表的时候都会对同一个列表操作,比如我们在函数体里面操作了一个 set ,list , 或者  dict  ,虽然我们没有返回内容,但是外部的内容还是会变的,所以我们要记得,不要给可变对象做为参数的时候加上默认值!
   def  my_function2(param=None):
   if param  is  None:
  param = []
  param.append("thing")
   return param
   结论
  正确的区分可变类型与不可变类型,对于我们深入了解python 是非常有 python 的,更多的关注技术细节,才能更好的拔高我们的技术水平
   番外
  我们在前言里面有提到的那个奇怪的问题,很显然,那是共享了字符串的字面量,这种Cpython 里面一个优化策略,叫驻留 (interning).CPython  还会在小的整数上使用这个优化措施,防止重复的创建 热门 数字,比如 0 -1 ,和 42 等等,但是 CPython 不会驻留所有的字符串和整数。比如如下的代码
   In [5]: c = 1
   In [6]: d = 1
   In [7]: id(c) Out[7]: 4297514912
   In [8]: id(d) Out[8]: 4297514912
   In [9]: e = 22569
   In [10]: f = 22569
   In [11]: e  is f Out[11]: False
   In [12]: c  is d Out[12]: True
  所以千万不要依赖字符串或者整数的驻留!比较字符串或者整数是否相等的时,应该使用==  而不是 is.  驻留是 python  解释器内部使用的一个特性。
来源:大鱼的博客
您还未登录,请先登录

热门帖子

最新帖子