python初学小结二:Import、字符串切片、列表的切片、enumerate()说明、字典、ptyhon-copy()与deepcopy()区别
1、import:
在python中要使用模块的某个功能时,我们必须要import相应的模块;
比如在python package :first(下有names.py)下面有一新的python包new(下有login.py),在names.py中import login,运行names.py时就会运行login.py的代码。
2、字符串切片:
name = "my name is cecilia hi"
print(name[name .find("is"):])#切片输出:is cecilia hi
3、Format,ljust,lstrip,maketrans:
name2 = "my name is {name} and I am {age} years old"
print(name2 .format(name ="cecilia",age=22 ) )#format()执行字符串格式化操作。
print(name2 .format_map( {'name':"cecilia","age":18 } ) )#用字典传参数,结果同上一句
输出结果:my name is cecilia and I am 18 years old
print(name2 .ljust(50,'*') )#字符串若不够50字符,*在后面补全
print('\ncecilia'.lstrip())#去掉左边的空格或回车,输出cecilia,还有rstrip(),strip()分别去掉右边和两边的空格和回车,具体解释见builtins.py
p = str.maketrans("abcdefli","1*@#$258")#把ab..换成1*...
print("cecilia".translate(p ) )#结果:@$@8581
如何转到函数的声明:比如你想看maketrans()函数的具体声明及其实现的功能解释,可以鼠标放在此函数上,按键“Ctrl+B”即可。
光标插入状态是细线,替换状态是粗线,按键盘上的Insert键可以切换
4、列表的切片
names = ["Lilei","Heyu",["cecilia","mumu"],"Zhangyang","Chenlin"]
print(names [-2:])#切片['Zhangyang', 'Chenlin']
print(names[0::2]) #0可以省去,表示打印从0到最后一个-1(切片步长是2)['Lilei', ['cecilia', 'mumu'], 'Chenlin']
4、enumerate()说明
enumerate()是python的内置函数,在字典上是枚举、列举的意思,对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值,enumerate多用于在for循环中得到计数。
enumerate()使用
(1)
for i,j in enumerate ('abcde'):#字符串
print(i,j)
# 0 a
# 1 b
# 2 c
# 3 d
# 4 e
for i,j in enumerate ([('a',1),('b',2),('c',3)]):#列表
print(i,j)
# 0('a', 1)
# 1('b', 2)
# 2('c', 3)
for i,j in enumerate ({'a':1,'b':2,'c':3}):#字典
print(i,j)
# 0 a
# 1 b
# 2 c
(2)
如果对一个列表,既要遍历索引又要遍历元素时,首先可以这样写:
list1 = ["这", "是", "一个", "测试"]
for i in range (len(list1)):
print i ,list1[i]
上述方法有些累赘,利用enumerate()会更加直接和优美:
list1 = ["这", "是", "一个", "测试"]
for index, item in enumerate(list1):
print index, item
>>>
0 这
1 是
2 一个
3 测试
enumerate还可以接收第二个参数,用于指定索引起始值,如:
list1 = ["这", "是", "一个", "测试"]
for index, item in enumerate(list1, 1):
print index, item
>>>
1 这
2 是
3 一个
4 测试
补充:
如果要统计文件的行数,可以这样写:
count = len(open(filepath, 'r').readlines())
这种方法简单,但是可能比较慢,当文件比较大时甚至不能工作。
可以利用enumerate():
count = 0
for index, line in enumerate(open(filepath,'r')):
count += 1
参考:http://blog.csdn.net/churximi/article/details/51648388
5、字典
#key - value 字典是没有下标的,因为可以通过key找值,无序
info = {
'stu1101': "Landi Li",
'stu1102': "Yusheng Wu",
'stu1103': "Xiaoyu Zhang",
}
for i in info:#更高效
print(i,info [i])
for k,v in info .items():#没那么高效,有把字典转成列表的过程
print(k,v)
b = {
'stu1101': "mumu",
1:3,
2:5
}
info.update(b)#把两个字典合并,中间有重复的覆盖,没有重复的添加
print(info )
print(info.items() )#把字典转换成列表:dict_items([('stu1101', 'mumu'), ('stu1102', 'Yusheng Wu'), ('stu1103', 'Xiaoyu Zhang'), (1, 3), (2, 5)])
info["stu1104"]="林立"
print(info )#添加一组key:value
#{'stu1101': 'Landi Li', 'stu1102': 'Yusheng Wu', 'stu1103': 'Xiaoyu Zhang', 'stu1104': '林立'}
删除字典数据:
del info ["stu1101"]
info .pop("stu1101")
6、ptyhon-copy()与deepcopy()区别
我们寻常意义的复制就是深复制,即将被复制对象完全再复制一遍作为独立的新个体单独存在。所以改变原有被复制对象不会对已经复制出来的新对象产生影响。
而浅复制并不会产生一个独立的对象单独存在,他只是将原有的数据块打上一个新标签,所以当其中一个标签被改变的时候,数据块就会发生变化,另一个标签也会随之改变。这就和我们寻常意义上的复制有所不同了。
对于简单的 object,用 shallow copy 和 deep copy 没区别
复杂的 object, 如 list 中套着 list 的情况,shallow copy 中的 子list,并未从原 object 真的「独立」出来。也就是说,如果你改变原 object 的子 list 中的一个元素,你的 copy 就会跟着一起变。这跟我们直觉上对「复制」的理解不同。
例如:
import copy
names = ["Lilei","Heyu",["cecilia","mumu"],"Zhangyang"]
names2 = names .copy() #浅copy
names2 = copy .deepcopy(names)#深copy
print(names)#['Lilei', 'Heyu', ['cecilia', 'mumu'], 'Zhangyang']
print(names2)#['Lilei', 'Heyu', ['cecilia', 'mumu'], 'Zhangyang']
names [1] = "何雨"
names [2][0] = "CECILIA"
print(names)#['Lilei', '何雨', ['CECILIA', 'mumu'], 'Zhangyang']
print(names2)#['Lilei', 'Heyu', ['cecilia', 'mumu'], 'Zhangyang']
7、python的数据存储方式
Python 存储变量的方法跟其他 OOP 语言不同。与其说是把值赋给变量,不如说是给变量建立了一个到具体值的 reference。
当在 Python 中 a = something 应该理解为给 something 贴上了一个标签 a。当再赋值给 a 的时候,就好象把 a 这个标签从原来的 something 上拿下来,贴到其他对象上,建立新的 reference。 这就解释了一些 Python 中可能遇到的诡异情况:
>> a = [1, 2, 3]
>>> b = a
>>> a = [4, 5, 6] //赋新的值给 a
>>> a
[4, 5, 6]
>>> b
[1, 2, 3]
# a 的值改变后,b 并没有随着 a 变
>>> a = [1, 2, 3]
>>> b = a
>>> a[0], a[1], a[2] = 4, 5, 6 //改变原来 list 中的元素
>>> a
[4, 5, 6]
>>> b
[4, 5, 6]
# a 的值改变后,b 随着 a 变了
上面两段代码中,a 的值都发生了变化。区别在于,第一段代码中是直接赋给了 a 新的值(从 [1, 2, 3] 变为 [4, 5, 6]);而第二段则是把 list 中每个元素分别改变。
而对 b 的影响则是不同的,一个没有让 b 的值发生改变,另一个变了。怎么用上边的道理来解释这个诡异的不同呢?
首次把 [1, 2, 3] 看成一个物品。a = [1, 2, 3] 就相当于给这个物品上贴上 a 这个标签。而 b = a 就是给这个物品又贴上了一个 b 的标签。
第一种情况:
a = [4, 5, 6] 就相当于把 a 标签从 [1 ,2, 3] 上撕下来,贴到了 [4, 5, 6] 上。
在这个过程中,[1, 2, 3] 这个物品并没有消失。 b 自始至终都好好的贴在 [1, 2, 3] 上,既然这个 reference 也没有改变过。 b 的值自然不变。
第二种情况:
a[0], a[1], a[2] = 4, 5, 6 则是直接改变了 [1, 2, 3] 这个物品本身。把它内部的每一部分都重新改装了一下。内部改装完毕后,[1, 2, 3] 本身变成了 [4, 5, 6]。
在此过程当中,a 和 b 都没有动,他们还贴在那个物品上。因此自然 a, b 的值都变成了 [4, 5, 6]。
搞明白这个之后就要问了,对于一个复杂对象的浅copy,在copy的时候到底发生了什么?
再看一段代码:
>>> import copy
>>> origin = [1, 2, [3, 4]]
#origin 里边有三个元素:1, 2,[3, 4]
>>> cop1 = copy.copy(origin)
>>> cop2 = copy.deepcopy(origin)
>>> cop1 == cop2
True
>>> cop1 is cop2
False
#cop1 和 cop2 看上去相同,但已不再是同一个object
>>> origin[2][0] = "hey!"
>>> origin
[1, 2, ['hey!', 4]]
>>> cop1
[1, 2, ['hey!', 4]]
>>> cop2
[1, 2, [3, 4]]
#把origin内的子list [3, 4] 改掉了一个元素,观察 cop1 和 cop2
浅copy对于一个复杂对象的子对象并不会完全复制,什么是复杂对象的子对象呢?就比如序列里的嵌套序列,字典里的嵌套序列等都是复杂对象的子对象。对于子对象,python会把它当作一个公共镜像存储起来,所有对他的复制都被当成一个引用,所以说当其中一个引用将镜像改变了之后另一个引用使用镜像的时候镜像已经被改变了。
所以说看这里的origin[2],也就是 [3, 4] 这个 list。根据 shallow copy 的定义,在 cop1[2] 指向的是同一个 list [3, 4]。那么,如果这里我们改变了这个 list,就会导致 origin 和 cop1 同时改变。这就是为什么上边 origin[2][0] = “hey!” 之后,cop1 也随之变成了 [1, 2, [‘hey!’, 4]]。
deepcopy的时候会将复杂对象的每一层复制一个单独的个体出来。
这时候的 origin[2] 和 cop2[2] 虽然值都等于 [3, 4],但已经不是同一个 list了。即我们寻常意义上的复制。