guxh的python笔记一:数据类型
1,基本概念
1.1,数据类型
基本数据类型:字符串,数字,布尔等
引用数据类型:相对不可变(元组),可变(列表,字典,集合等)
基本数据类型存放实际值,引用数据类型存放对象的地址(即引用)
==:判断值是否相等
is:判断id是否相等,即内存地址,id()可以返回内存地址
1.2,序列类型
容器类型:list,tuple,collections.deque,存放引用,可嵌套
扁平序列:str,bytes,bytearray,memoryview,array.array,存放值,只包含原子数据
可变序列:list,bytearray,array.array,collections.deque,memoryview
不可变序列:tupe,str,bytes
2,str
1)格式化:
%s:'%s plus %s equals %s' % (1, 1, 2)
2)find/rfind:返回最左边/最右边索引,没有返回-1,例如路径中提取文件名
s1 ='c:/../../text.txt' s1[s1.rfind('/')+1: s1.find('.txt')] # s1结果是text
3)lower/upper:小写/大写
4)startswith/endswith:判断开始/判断结尾,例如endswith('com'),接受多个参数时必须用元组name.endswith(('.c', '.h'))
5)strip/lstrip/rstrip:去除两边/左边/右边的空格字符串,也可以传参指定去除的内容
6)join:合项
','.join(['a', 'b', 'c']) # 结果是a,b,c
7)split:裂项,不传参就对空格、制表、换行进行分割
'a b \nc'.split(),# 结果是['a', 'b', 'c']
8)count:统计出现次数
9)index:判断索引位置
10)replace:替换,默认全替,但可以传第3参数指定替换几个
'aba'.replace('a', 'b', 1) # 指定替换1个,结果是'bba',
11)center:居中打印
'title'.center(50, '-') # 结果是'----------------------title-----------------------'
12)isdigit:判断数字
'322'.isdigit() # 结果是True
3,bytes
码位:每个字符占若干字节,python3(str),python2(unicode)
字节序列:每个字符占一个字节,python3(bytes),python2(str/bytes)
4,列表
4.1,list函数
功能一:用于将可迭代对象iterator转换为列表
功能二:实现浅拷贝
例如:
list('hello') # 结果是['h','e','l','l','o'] list(range(5)) # 结果是[1, 2, 3, 4, 5] list({'a': 1, 'b': 2}) # 结果是['a', 'b'],因为对字典迭代获取到的是key
4.2,list操作
1)增:lista.append(4),就地添加返回None
2)删:删元素用del、remove、pop;删列表用del、clear
3)改:lista[2] = 2
4)插:lista.insert[3, 'insert_value'],或者:lista[3:3] = ['insert_value']
7)切片:访问切片:y=x[1:3];插入序列x[1:1] = [2,3,4];删除序列:x[1:4]=[];替换序列:x[1:4]=[2,3,4]
8)extend追加:就地加lista.extend(listb),等效于lista = lista + listb,或者lista[len(lista):] = listb
9)列表相加:lista + listb,原序列不会变
10)乘法:[1,2,3] * 2,结果为[1,2,3,1,2,3],原序列不变
11)创建5个空序列:
lists = [[] for i in range(5)] # 5个不同的空序列 lists = [[]] * 5 # 5个id相同的空序列
12)reverse / reserved:反向存放,lista.reverse()就地反向无返回值,reversed(list)有返回值(原序列不变)
13)sort / sorted:排序,x.sort()就地排序无反向值,sorted(list)有返回值(原序列不变)
14)copy:浅拷贝,list.copy()
15)enumerate:遍历index和value
for i,v in enumerate(lista): print(i, v) # i索引,v值
16)in,len,max,min,index,count:略
4.3,列表的拷贝
t = [1, [2, 3], (4, 5)]
起别名,连第一层都不拷贝:
a = t
浅拷贝:拷贝第一层:
b = list(t) b = t[:] b = t.copy() b = copy.copy(t)
深拷贝:拷贝所有层:
c = copy.deepcopy(t)
看看有什么区别:
t[0] = 0 t[1].append(0) t[2] += (0, )
输出结果:
t : [0, [2, 3, 0], (4, 5, 0)] a : [0, [2, 3, 0], (4, 5, 0)] # 别名,全跟着变 b : [1, [2, 3, 0], (4, 5)] # 浅拷贝,第一层以及第二层内的不可变序列不变,第二层的可变序列跟着变 c : [1, [2, 3], (4, 5)] # 深拷贝,全都不变
总结:
判断时可以用is或者id(),看下不同的变量名,是否指向同一引用对象
a和t的id完全相同,b/c和t的id不同
如果列表内部有“可变的引用对象”(例如字典、集合、列表,元组算不可变的引用对象),t发生改变时,会影响到浅拷贝b,但不会影响到深拷贝c
5,元组
5.1,tupple函数
和list函数一样,将某个序列转换为tupple
5.2,元组操作
1)切片:只支持切片访问即查,不支持插,删,改
2)元组相加:tu1 + tu2,原序列不会变
3)乘法:(1,2,3) * 2,结果为(1,2,3,1,2,3),原序列不变
4)in,len,max,min,index,count,enumerate:略
5.3,元组和列表的区别
列表不建议存放不同类型的东西,否则无法排序
元组经常用来存放不同类型的东西
5.4,具名元组
具有名字的元组
from collections import namedtuple TU = namedtuple('manincity', 'name city') tu1 = TU('guxh', 'shanghai') print(tu1) # manincity(name='guxh', city='shanghai')
6,字典
6.1,字典的创建
d = {'a':1, 'b':2, 'c':3} d = dict(a=1, b=2, c=3) d = dict([('a','1'), ('b',2), ('c',3)]) # 元组列表,列表列表都可以,只要是2个值的小序列组成的大序列,不用写字典推导了!!!
6.2,字典操作
1)增和改:d['d'] = 4,有改/无增
2)d.update(d2),用字典d2区更新d,有改/无增
3)删除
d.pop('d') # 删除key-values键值对 del d['a'] # 删除key-values键值对 popitem() # 删最后一个,由于字典是无序的所以实际上是随机删一个
4)清空字典
y = d d.clear() # 无返回值,d和y都能清掉 d = {} # 直接赋空值也可以清,只能清d
5)查
'a' in d # 判断是否含有键为K的项,list中是判断的是值 d['a'] # 返回关联键K的value,如果不存在会报错KeyError d.get('a', 123) # 有就返回value,没有则返回缺省值123
6)copy
d2 = d1.copy() # 是浅拷贝,替换值时原始字典不受影响,但是修改值是原始字典也会改变。 d2 = d1.deepcopy() # 深拷贝
7)fromkeys
从给定的key创建新字典,可以指定values,默认为None
d = dict.fromkeys(['east', 'west'], 20) # dict可以改成任何已经存在的字典,但是结果和该字典无任何关系 print(d) # {'west': 20, 'east': 20}
8)has_key:检测是否有key
9)items/iteritems, keys/iterkeys, values/itervalues:返回值/迭代对象
d = {'west': 10, 'east': 20, 'south':30, 'north':40} print d.items() # [('west', 10), ('east', 20), ('north', 40), ('south', 30)],即字典转列表 print d.keys() # ['west', 'east', 'north', 'south'] print d.values() # [10, 20, 40, 30]
直接对字典进行循环获取的是keys
10)len:略
6.3,字典应用-统计单词出现的位置
sentence = """I'm a big big girl in a big big world It's not a big big thing if you leave me but I do do feel that I too too will miss you much""" sentence = sentence.split() d = {}
方法一:
for index, word in enumerate(sentence): if word not in d: d[word] = [] d[word].append(index)
方法二:get
for index, word in enumerate(sentence): temp = d.get(word, []) temp.append(index) d[word] = temp
方法三:setdefault
for index, word in enumerate(sentence): d.setdefault(word, []) d[word].append(index)
方法三(合一句):setdefault
for index, word in enumerate(sentence): d.setdefault(word, []).append(index)
方法四:defaultdict
from collections import defaultdict d = defaultdict(list) for index, word in enumerate(sentence): d[word].append(index)
6.4,其他
1)字符串格式化时可以使用字典
phonebook = {'cecil' : 56845 } "cecil's phone number is %(cecil)s." % phonebook
2)根据values求最小值,最大值,排序
d = {'a': 10, 'b':6, 'c': 5, 'd':17, 'e':12}
方法一:zip
min(zip(d.values(), d.keys())) # (5, 'c') max(zip(d.values(), d.keys())) # (17, 'd') sorted(zip(d.values(), d.keys())) # [(5, 'c'), (6, 'b'), (10, 'a'), (12, 'e'), (17, 'd')]
方法二:lambda
d[min(d, key=lambda k: d[k])] # 5 d[max(d, key=lambda k: d[k])] # 17 [d[i] for i in sorted(d, key=lambda k: d[k])] # [5, 6, 10, 12, 17]
3)对字典使用集合的操作:字典的keys()和items()支持集合操作,但values()不支持
d1 = {'a': 1, 'b': 2, 'c': 3} d2 = {'b': 4, 'c': 3, 'd': 6} d1.keys() & d2.keys() # {'b', 'c'} d1.keys() - d2.keys() # {'d'} d1.items() & d2.items() # {('c', 3)} {key: d1[key] for key in d1.keys() - {'c'}} # {'b': 2, 'a': 1}
7,集合
集合最重要的2个内容:
去重(把列表变成集合就自动去重了)
关系测试(测试2组数据的交集、差集、并集)
list1 = [1, 3, 5, 6, 7, 8, 1, 3, 5, 7, 2, 3] list1 = set(list1) # {1, 2, 3, 5, 6, 7, 8} 集合也是无序的 list2 = {1, 3, 11, 22, 55, 78, 90, 90, 1, 3} # 实际结果是{1, 3, 11, 78, 22, 55, 90} print(list1.intersection(list2)) # 取交集,结果是{1,3} print(list1.union(list2)) # 取并集,结果是{1, 2, 3, 5, 6, 7, 8, 11, 78, 22, 55, 90} print(list1.difference(list2)) # 取差集,结果是{2, 5, 6, 7, 8},list1里有的,但是list2里没有的 print(list1.issubset(list2)) # 判断list1是否是list2的子集 print(list1.issuperset(list2)) # 判断list2是否是list1的父集
如果集合是空集,必须写成set(),写成{}是字典
7.1,集合运算的符号
& 交集
| 并集
- 差集
^ 对称差集
7.2,集合操作
1)增
t.add(5) # 增加一项,注意增加是add,不是append t.update(5,6,7) # 增加多项
2)删
t.remove(5) # 删除5,如果set中不存在5则会报错 t.discard(5) # 删除5,如果set中不存在5则不会报错 a = t.pop() # 随机删除一个值,并且把该值返回给a
3)len,in,copy:略
7.3,集合去重
a = [1, 3, 5, 1, 7, 3, 9, 2, 6, 1, 3]
去重:
set(a) # {1, 2, 3, 5, 6, 7, 9}
去重保持顺序不变,序列中的元素可hash:
def dedupe(items): seen = set() for item in items: if item not in seen: yield item # 不用generator的话,还要在新建个列表,然后用该列表append并返回值 seen.add(item) list(dedupe(a)) # [1, 3, 5, 7, 9, 2, 6]
去重保持顺序不变 ,序列中的元素不可hash,要先想办法转成可哈希(待补充)
8,其他类型
数字(略)
布尔类型(略)
9,数据运算
9.1,运算符
+,-, *, /:加减乘除
%:取模
**:次方,即幂
//:整除,返回商的整数部分
9.2,比较运算
==:等于
!= : 不等于
<>:不等于
>:大于
<:小于
>=:大于等于
<=:小于等于
9.3,赋值运算
=:等于
+=:A+=B即A=A+B,下同
-=:
*=:
/=:
%=:
**=:
//=:
9.4,逻辑运算
and
or
not
and或者or可以连接多个,例如 a and b and c,还可以加or,例如a and b and c or d,即(a and b and c) or d
9.5,成员运算
in:判断值是否在序列中
not in:判断值是否在序列中
9.6,身份运算
is:id是否一样,类型是否是XXX等等,例如type(a) is list
is not
9.7,位运算
&:与
|:或
^:异或
~:反
<<:左移动
>>:右移动
9.8,三元运算
result = value1 if condition else value2
9.9,boolean表达式
result = a or b # 如果a是真result=a,如果a是假result=b
备注:写boolean可能会代码难以阅读,建议使用三元运算,或者辅助函数
10,操作数据
10.1,各类推导式
列表推导:
[i for i in range(10) if i > 5]
生成器表达式:
(i for i in range(10) if i > 5)
集合推导:
{i for i in range(10) if i > 5}
字典推导:
prices = {'ACME': 31, 'AAPL': 26, 'IBM': 29, 'HPQ': 35, 'FB': 33} items = ('ACME', 'IBM', 'FB') {key: value for key, value in prices.items() if value > 30} # {'ACME': 31, 'HPQ': 35, 'FB': 33} {key: value for key, value in prices.items() if key in items} # {'ACME': 31, 'IBM': 29, 'FB': 33} # 另一种形式: dict((key, value) for key, value in prices.items() if value > 30) # {'ACME': 31, 'HPQ': 35, 'FB': 33}
注意:没有元组推导
11,切片
11.1,切片原理
“[]”运算符是交给__getitem__和__setitem处理的(详见guxh的python笔记:类的属性)
class Seq: def __init__(self, components): self.components = components def __getitem__(self, index): return self.components[index] s = Seq([1, 2, 3, 4, 5, 6]) print(s[0]) # 1 print(s[0:3]) # [1, 2, 3]
对s[0],s[0:3]的取值委托给了self.components[index]处理,看看self.components拿到的index到底是什么?
class Seq: def __getitem__(self, index): return index s = Seq() print(s[0]) # 0 print(s[0:3]) # slice(0, 3, None) print(type(s[0:3])) # <class 'slice'> print(dir(s[0:3])) # 有'indices', 'start', 'step', 'stop'这些方法
S.indices(len) —> (start, stop, stride)
给定长度为len的序列,计算start,stop,stride,超出边界的索引被截掉。
11.2,切片技巧
序列反转:
>>> s = [1, 2, 3, 4] >>> s[::-1] [4, 3, 2, 1]
12,不同数据类型的传参
可以参考一篇文章:《Python学习系列之值类型与引用类型》
摘取如下:
C++中是传值和传引用(指针)。c语言加上*号传递指针就是引用传递,而直接传递变量名就是值传递)
Java是传值(传值和传引用,只不过引用就是内存地址,所以也是值)。Java里区分值和引用,是因为值存储在栈里,而引用对象存储在堆里(引用本身在栈里)。
而Python所有的都是对象,都是引用,所以所谓的值类型都是不可变类型。类似于Java的字符串类型。
所以Python中的参数传递都是传递引用,也就是传递的是内存地址。只不过对于不可变类型,传递引用和传递值没什么区别。而对于可变类型,传递引用是真的传递内存的地址。
听说python只允许引用传递是为方便内存管理,因为python使用的内存回收机制是计数器回收,就是每块内存上有一个计数器,表示当前有多少个对象指向该内存。每当一个变量不再使用时,就让该计数器-1,有新对象指向该内存时就让计数器+1,当计时器为0时,就可以
收回这块内存了。当然还有其他的GC方法,否则计数器回收,无法解决循环引用的问题。