Python学习笔记三:03深复制和浅复制

@TOC

一、字符串的拼接

  例: a = 'hello' , b = 'python', c = '!',将a,b ,c 中的字符串连成一句话。

1. 用+号

>>> s='i love python'
>>> s1='!!'
>>> s+s1  #'i love python!!'

2. 格式化字符串 %s

  格式化字符串的%s部分称为转换说明符,标记了需要放置转换值的位置,通用术语为占位符。在有多个占位符的字符串中,可以使用元组(还有字典)传入多个格式化值。

>>> s='i'
>>> s1='love'
>>> s2='python'
>>> s3='%s '%s   #'i ' 单个可括号%(s)也可以不用%s
>>> s3='%s %s %s '%(s,s1,s2)   #'i love python ' 

  一一对应的(占位符)输出来的还是字符串
在上面的示例中,s表示百分号右边的值会被格式化为字符串,s指的是str。

3. ''.join()方法

  s.join(iterable) -> str
  只有一个参数,对象必须是可迭代(列表,元组,字符串)的,并且元素必须是字符串

>>> ''.join([s,s1,s2]) #'ilovepython'
>>> ' '.join([s,s1,s2]) #'i love python' 加了个空格
>>> ' '.join((s,s1,s2)) #用元组
>>> ' '.join('s,s1,s2') #失去了变量含义

4. '{}'.format(s)

  这里的基本思想是对字符串调用方法format,并提供要设置其格式的值。字符串包含有关如何设置格式的信息,而这些信息是使用一种微型格式指定语言指定的。每个值都被插入字符串中,以替换通花括号括起的替换字段。要在最终结果中包含花括号,可在格式字符串中使用两个花括号来指定。

>>> "{{ceci n'est pas une}}".format()   #{ceci n'est pas une}

  在格式字符串中,最激动人心的部分为替换字段。替换字段由如下部分组成,其中每个本分都是可选的。

  • 字段名:索引或标识符,指出要设置哪个值的格式并使用结果来替换该字段。除指定值外,还可指定值的特定部分,如列表的元素。
  • 转换标志:跟在叹号后面的单个字符。当前支持的字符包括r(表示repr)、s(表示str)和a(表示ascii)。如果你指定了转换标志,将不使用对象本身的格式设置机制,而是使用指定的函数将对象转换为字符串,再做进一步的格式设置。
  • 格式说明符:跟在冒号后面的表达式(这种表达式是使用微型格式指定语言表示的)。格式说明符让我们能够详细地指定最终的格式,包括格式类型(如字符串、浮点数或十六进制数),字段宽度和数的精度,如何显示符号和千位分隔符,以及各中对齐和填充的方式。
      在最简单的情况下,只需向format提供要设置其格式的未命名参数,并在格式字符串中使用未命名字段。此时,将按顺序将字段和参数配对。你还可给参数指定名称,这种参数将被用于相应的替换字段中。你可混合使用这两种方法。
>>> ’{foo} {} {bar} {}’.format(1,2,bar=4,foo=3) # 3 1 4 2

  还可以通过索引来指定要在哪个字段中使用相应的未命名参数,这样可不按顺序使用未命名参数。

>>> ’{foo} {1} {bar} {0}’.format(1,2,bar=4,foo=3)   # 3 2 1 4

  然而,不能同时使用手工编号和自动编号,因为这样很快会变得混乱不堪。

>>> '{} {}'.format(s)    #IndexError: tuple index out of range
>>> '{} {}'.format(s,s1)     # 'i love'

  当{}里面是空的时候,里面默认索引为0,1按format括号里的顺序依次填入

>>> '{0} {1} {2}'.format(s,s1,s2) # 有索引的
>>> '{1} {2} {0}'.format(s,s1,s2) # 可以变顺序
>>> '{1} {1} {1}'.format(s,s1,s2) # love love love
>>> '{0} {0} {0}'.format([s,s1,s2]) # "['i', 'love', 'python'] ['i', 'love', 'python'] ['i', 'love', 'python']" # 因为[s,s1,s2]为0索引,这里没有1索引。
>>> '{0[0]} {0[1]} {0[2]}'.format([s,s1,s2]) #'i love python'
>>> #'{0} {0} {0}'.format(a=s,b=s1,c=s2) # 指定了对象后,会失去位置,运行报错
#IndexError: tuple index out of range(前面也要指定)

  {}里面可以指定对象名称,后面通过赋值的方式给前面的相应的值,后面是无序的

>>> '{a} {c} {b}'.format(a=s,b=s1,c=s2) # 后面指定了之后,前面必须要用名字指定位置

  还可以使用句点表示法来访问导入的模块中的方法、属性、变量和函数。

>>> import math
>>> tmpl='The {mod.__name__} module defines the value {mod.pi} for '
>>> tmpl.format(mod=math)   #'The math module defines the value 3.14 for '

二、format补充

1. 基本转换

  指定要在字段中包含的值后,就可添加有关如何设置其格式的指令了。首先可以提供一个转换标志。

>>> print('{pi!s} {pi!r} {pi!a}'.format(pi=''))
# '' '\u03c0'

  上述三个标志制定分别使用str、repr和ascii进行转换。函数str通常创建外观普通的字符串版本。函数repr尝试创建给定值的Python表示。函数ascii创建只包含ASCII字符的表示。
  你还可指定要转换的值是哪种类型,更准确地说,是要将其视为哪种类型。例如你可能提供一个整数,但将其作为小数进行处理。为此可在格式说明符(即冒号:后面)使用字符f(表示定点数)。

>>> '{}'.format(12.22)
>>> 'The numbei is {num:f}’.format(num=42)  #'The number is 42.00000'

  你也可以将其作为二进制数进行处理。

>>> 'The numbei is {num:b}’.format(num=42)  #'The number is 101010'

表3-1 字符串格式设置中的类型说明符

类型 含义
b 将整数表示为二进制数
c 将整数解读为Unicode码点
d 将整数视为十进制数进行处理,这是整数默认使用的说明符
e 使用科学表示法来表示小数(用e来表示指数)
E 与e相同,但是用E来表示指数
f 将小数表示为浮点数
F 与f相同,但对于特殊值(nan和inf),使用大写表示
g 自动在定点表示法和科学表示法之间做出选择。这是默认用于小数的说明符,但在默认情况下至少有1位小数
G 与g相同,但使用大写来表示指数和特殊值
n 与g相同,但插入随区域而异的数字分隔符
o 将整数表示为八进制数
s 保持字符串的格式不变,这是默认用于字符串的说明符
x 将整数表示为十六进制数并使用小写字母
X 与x相同,但使用大写字母
% 将数表示为百分比值(乘以100,按说明符f设置格式,再在后面加上%)

2. 宽度、精度和千位分隔符

  设置浮点数(或其他更具体的小数类型)的格式时,默认在小数点后面显示6位小数,并根据需要设置字段的宽度,而不进行任何形式的填充。
  宽度是使用整数指定的。

>>> '{num:10}'.format(num=3)            #'         3'
>>> '{name:10}'.format(name='Bob')  #'Bob       '

  如你所见,数和字符串的对齐方式不同。
  精度也是使用整数指定的,但需要在它前面加上一个表示小数点的句点。

>>> '{:.1f}'.format(12.22)  #'12.2'  保留1位小数
>>> '{:.1}'.format(12.22)   #'1e+01'
>>> '{:.2%}'.format(12.2222) #'1222.22%'  百分比

  这里显示地指定了类型f,因为默认的精度处理方式稍有不同。当然,可同时指定宽度和精度。

>>> '{pi:10.2f}'.format(pi=3.14159) #'      3.14'

  实际上,对于其他类型也可指定精度,但是这样做的情形不太常见。

>>> ’{:.5}’.format('Guido van Rossum’)  #'Guido'

  最后,可使用逗号来指出你要添加千位分隔符。

>>> 'One googol is {:,}'.format(10*100) #'One googol is 1,000'

  同时指定其他格式设置元素时,这个逗号应放在宽度和表示精度的句点之间。

3. 符号、对齐和用0填充

  在指定宽度和精度的数前面,可添加一个标志。这个标志可以使零、加号、减号或空格,其中零表示使用0来填充数字。

>>> '{:010.2f}'.format(3.14)    #'0000003.14'

  要指定左对齐、右对齐和居中,可分别使用<、>和^。

>>> '{:<10}'.format(12)     #'12        ' 
>>> '{:>10}'.format(12)     #'        12' 
>>> '{:^10}'.format(12)     #'    12    '  

  可以使用填充字符来扩充对齐说明符,这样将使用指定的字符而不是默认的空格来填充。

>>> '{:*^10}'.format(12)        #'****12****' 用*来填充
>>> '{:a^10}'.format(12)    #'aaaa12aaaa'

  还有更具体的说明符=,它指定将填充字符放在符号和数字之间。

>>> print('{0:10.2f}\n{1:10.2f}'.format(3.14,-3.14))    
#      3.14
#     -3.14
>>> print('{0:10.2f}\n{1=:10.2f}'.format(3.14,-3.14))   
#      3.14
#-     3.14

  如果要给正数加上符号,可使用说明符+(将其放在对齐说明符后面),而不是默认的-。如果将符号说明符指定为空格,会在正数前加上空格而不是+。

>>> print('{0:+.2}\n{1:+.2}'.format(3.14,-3.14))    
#+3.1
#-3.1
>>> print('{0: .2}\n{1: .2}'.format(3.14,-3.14))    

# 3.1
#-3.1

  要介绍的最后一个要素是#号,你可将其放在符号说明符和宽度之间。这个选项将触发另一种转换方式,转换细节随类型而异。例如,对于二进制、八进制和十六进制转换,将加上一个前缀。

>>> '{:#b}'.format(42)  #'0b101010'
对于各种十进制数,它要求必须包含小数点(对于了类型g,它保留小数点后面的零)。
>>> '{:#g}'.format(42)  #'42.0000'

三、格式化输出

表4-2 字符串格式化符号

符号 描述
%c 格式化字符及其ASCII码
%s 格式化字符串
%d 格式化整数
%u 格式化无符号整型
%o 格式化无符号八进制数
%x 格式化无符号十六进制数
%X 格式化无符号十六进制数(大写)
%f 格式化浮点数字,可指定精度
%e 用科学表示法格式化浮点数
%E 与e相同
%g %f和%e的简写
%G %F和%E的简写
%p 用十六进制数格式化变量的地址

1. %s 格式化字符串

  整数既可以使用%s也可以使用%d进行格式化。

>>> print('小智今年%s岁了'%10)        #'小智今年10岁了'
>>> print('小智今年%d岁了'%10)        #'小智今年10岁了'
>>> '%s'%'lucky'    #'lucky'
>>> '%8s'%'lucky'  #' lucky' 默认右对齐,前面用空格补齐 前面加数字表示宽度
>>> '%-8s'%'lucky' #'lucky ' -号表示左对齐
>>> '%s'%'%'        #%
>>> '%*s'% (10.56) # '       565'

2. %d 格式化整数

>>> '%d'%1.11           #'1' 输出的还是字符串
>>> print('%d'%1.111)   #1 格式化整数

3. %f 格式化小数

  若不指定精度,则默认输出6位小数

>>> '%f'%1.111  #'1.111000' 默认保留6位小数

  m.n m是显示的最小长度,当m大于格式化位数时才起作用显示m位,n是代表小数的位数。因为格式化说明符以表示类型的字符结束,所以精度应该放在类型字符前面。

>>> '%2f'%1.111     #'1.111000'

  长度为2,又保留6位小数,相当于2.6。默认先看精度

>>> '%.2f'%1.111    #'1.11'保留2位小数
>>> '%6.2f'%1.111       #' 1.11'
>>> '%2.1f'%123.111111 #'123.1' 优先以精度为准
>>> '%06.2f'%1.111  #'001.11' #用0填充

4. %c 格式化ASCII字符(把数字转换成字母)

>>> 'a'>'A'     #True
>>> '%c'%65     #'A'
>>> '%c'%97     #'a'

5. %o 格式化八进制

>>> '%o'%7  #'7'
>>> '%o'%8  #'10'
>>> '%o'%16     #'20

6. %x 格式化十六进制

>>> '%x'%16     #'10'
>>> '%x'%10     #'a'
>>> '%x'%15     #'f'

7. %e 用科学计数法格式化

>>> '%e'%100    #'1.000000e+02'

8. 百分号的格式化

  在Python中,字符串中的百分号是转换说明符,如果要输出%,就需要格式化字符%,从而需要使用%%。

>>> print('输出百分号:%s'%'%')       #输出百分号:%

9. 字符串格式化元组

  格式化操作符的右操作数可以使任何元素。如果是元组或映射类型(如字典),那么字符串格式化将会有所不同。我们尚未涉及到映射(字典),这里先了解一下元组。
  如果右操作数是元组,其中每一个元素都会被单独格式化,每个值都需要一个对应的转换说明符。

>>> print('今年是%s年,将举办第%s届奥运会,有%d个国家参加'%('2012','28',26))
#今年是2012年,将举办第28届奥运会,有26个国家参加
>>> print('今年是%s年,将举办第%s届奥运会,有%d个国家参加'%'2012','28',26)
# TypeError: not enough arguments for format string

  由以上输出结果看到,在有多个占位符的字符串中,可以是用元组传入多个格式化值。只有元组和字典可以格式化一个以上的值。

四、基本转换说明符

下面介绍基本转换说明符。注意,这些项的顺序至关重要:

  1. %字符:标记转换说明符开始
  2. 转换标志(可选):-表示左对齐;+表示在转换值之前要加上正负号;0表示转换值位数不够时用0填充(大于0的话会被认成字段宽值);" "(空字符)表示正数之前保留空格
  3. 最小字段宽度(可选):转换后的字符串至少应该具有该值指定的宽度。如果是*,宽度就会从值元组中读出
  4. 点(.)后跟精度值(可选):如果转换的是实数,精度值表示出现在小数点后的位数;如果转换的是字符串,该数字就表示最大字段宽度;如果是*,精度就会从元组中读出
  5. 转换类型:如表4-2

下面将详细讨论这五个注意项。

1. 简单转换

  简单转换只需要写出转换类型。

>>> print('圆周率PI的值为:%.2f'%3.14)     #圆周率PI的值为:3.14

2. 字段宽度和精度

  转换说明符包括字段宽度和精度。字段宽度是转换后的值所保留的最小字符个数,精度是数字转换结果中应该包含的小数位数或字符串转换后的值所能包含的最大字符个数。

>>> print('圆周率PI的值为:%10f'%3.141593)     #圆周率PI的值为:  3.141593

  字符串宽度为10,被字符串占据8个空格,剩余2个空格。

>>>  print('圆周率PI的值为:%10.2f'%3.141593)  #圆周率PI的值为:      3.14

  字符串宽度为10,被字符串占据4个空格,剩余6个空格。

>>> print('圆周率PI的值为:%.2f'%3.141593) #圆周率PI的值为: 3.14
>>> print('字符串精度获取:%.5s'%('hello world'))   #字符串精度获取:hello

  打印字符串前5个字符
  由输出结果可知,字段宽度和精度都是整数,并通过点号(.)分隔。两个都是可选参数,如果给出精度,就必须包含点号。

>>> print('从元组中获取字符串精度:%*.*s'%(10,5,'hello world'))
    #从元组中获取字符串精度:     hello
>>> print('从元组中获取字符串精度:%.*s'%(5,'hello world'))
    #从元组中获取字符串精度:hello

  由输出结果看到,可以使用(星号)作为字段宽度或精度(或两者都用)。数值会从元组中读出。

3. 符号、对齐和0填充

  在字段宽度和精度之前可以放置一个“标表”,可以是零、加号、减号或空格。
  零表示用零填充。

>>> print('圆周率PI的值为:%010.2f'%3.141593)  #圆周率PI的值为:0000003.14

  减号(-)用来对齐数值。

>>> print('圆周率PI的值为:%10.2f'%3.14)   #圆周率PI的值为:      3.14
>>> print('圆周率PI的值为:%-10.2f'%3.14)  #圆周率PI的值为:3.14      

  空白(" ")表示在正数前加上空格,该操作用于数值的对齐。

>>> print(('%5d'%10)+'\n'+('%5d'%-10))
#   10
#  -10

  加号(+)表示无论是正数还是负数都表示出符号,该操作也用于数值的对齐。

>>> '%+6.2f'%-1.111     #' -1.11'

四、转义字符

表3-1 Python中的转义字符

转义字符 描述 转义字符 描述
\ 续行符 \n 换行
\ 反斜杠符号 \v 纵向制表符
' 单引号 \t 横向制表符
" 双引号 \r 回车
\a 响铃(在cmd中) \f 换页
\b 退格(Backspace) \oyy 八进制数,yy代表的字符,如\o12表示换行
\e 转义 \xyy 十六进制数,yy代表的字符,如\x0a代表换行
\000 \other 其他字符以普通格式输出
>>> print('www\nmmm')
>>> print(r'www\nmmm')  #取消字符串的转义
>>> print(r'www\\nmmm')     #取消转义
>>> print('\a')
>>> print('abde\b')
>>> print('abc\ttt')

五、深浅复制 (有嵌套的列表)

  元组和列表之间的相互嵌套(字符串里面都会变成字符串,失去列表和元组的方法),嵌套之后可以通过索引值来取数
  复制都是分配俩个地址,只不过浅复制只能复制外面的,复制不了嵌套在里面的
  同一个地址针对的是嵌套在里面序列类型
·浅复制:copy() 切片
·深复制:import copy copy.deepcopy()

>>> li=['a','b']
>>> lu=[1,li]
>>> lu      #[1,['a','b']
>>> lu[1][1]    #'b'
>>> lq=lu.copy() #[1,['a','b'] 属于浅复制
>>> id(lu)  #57977352
>>> id(lq)      #58255120
>>> id(lu[1])  #57977832
>>> id(lq[1])  #57977832
>>> import copy
>>> ls=copy.deepcopy(lu) #[1, ['a', 'b']]
>>> id(lu[1])  #57977832
>>> id(ls[1])  #58069800

说明内列表变了

>>> li.append('c')
>>> li #['a', 'b', 'c']
>>> lq #[1,['a', 'b', 'c']] #浅复制还是同一个对象
>>> ls #[1, ['a', 'b']]  #深复制不是同一个对象了

>>> lqq=lu[:]       #[1, ['a', 'b', 'c']]
>>> li.append('d') #[1, ['a', 'b', 'c', 'd']]

你可能感兴趣的:(Python学习笔记三:03深复制和浅复制)