这篇博客主要是阅读python之旅 时做的笔记。提取出最主要的知识点,供个人在以后中快速查阅。
下面是该书的主要脉络。
ASCII,Unicode以及UTF-8是较为常用的三种字符编码。 简单来说ASCII占一个字符,只规定了128个字符,但是Unicode是四个字节的,如果表示某些只要一个字节的字符,显然就浪费存储空间。因此在Unicode的基础上,人们开发出了UTF-16,UTF-32和UTF-8。 UTF-8是用一个字节到四个字节来表示字符。 在UTF-8中,ASCII字符仍旧用一个字节表示,阿拉伯文、希腊文等使用两个字符表示,常用汉字用三个字符表示。
简单来说python2有两种字符串类型,str和unicode,两种类型可以用decode和encode相互转换。Unicode类型的字符串定义前面加个u,比如 u’小兵’
用 Python2 编写程序的时候经常会遇到 UnicodeEncodeError 和 UnicodeDecodeError,它们出现的根源就是如果代码里面混合使用了 str 类型和 unicode 类型的字符串,Python 会默认使用 ascii 编码尝试对 unicode 类型的字符串编码 (encode),或对 str 类型的字符串解码 (decode),这时就很可能出现上述错误。
在进行同时包含str 类型和 unicode 类型的字符串操作时,Python2 一律都把 str 解码(decode)成 unicode 再运算,这时就很容易出现 UnicodeDecodeError。 解决方法是直接用指定’utf-8’编码,>>> s = '你好' # str 类型,utf-8 编码>>> u = u'世界'>>>>>> s.decode('utf-8') + u # 显示指定 'utf-8' 进行转换u'/u4f60/u597d/u4e16/u754c' # 注意这不是错误,这是 unicode 字符串如果函数或类等对象接收的是 str 类型的字符串,但你传的是 unicode,Python2 会默认使用 ascii 将其编码成 str 类型再运算,这时就很容易出现 UnicodeEncodeError。raw_input只接受str类型的字符串
>>> name = raw_input('输入你的姓名:')输入你的姓名: 小明>>> name'/xe5/xb0/x8f/xe6/x98/x8e'>>> type(name)<type 'str'>怎样让输入的字符串变成Unicode的呢?
>>> name = raw_input(u'输入你的姓名: '.encode('utf-8')).decode('utf-8') # 推荐输入你的姓名: 小明>>> nameu'/u5c0f/u660e'>>> type(name)<type 'unicode'>Python2 提供了 input,raw_input,PRint 等用于输入输出,但在 Python3 中发生了一些改变,raw_input 已经没有了,input 的用法发生了变化,print 也从原来的语句变成了一个函数。本文将对这两种情况进行介绍。
废话不多说,一句话raw_input就是将所有的输入都转换成一个字符串。 而如果用input的话,输入数字就是数字的类型,输入字符串得用’ ‘啊啊啊。
python3中的input就是python2的raw_input,当然想要用python2的input就得这样 eval(input()),就是将字符串str当成有效的表达式来求值并返回计算结果
python2中,print时可加可不加括号。python3中就一定得加括号。
print 默认是换行输出的,如果不想换行,可以在末尾加上一个 `,’,比如:
>>> for i in range(0, 3):... print i...012>>> for i in range(0, 3):... print i, # 加了 ,...0 1 2 # 注意会加上一个空格一般来说总说很重要。。 简单来说python中主要有5种数据类型。当然咯,就是 列表,元组,字符串,字典和集合。 序列类型: 列表、元组、字符串 其他类型:字典和集合
其实就是一句话:只要是序列就有公共的通用操作: - 索引 - 分片 - 迭代 - 加 - 乘 - 检查某元素是否属于序列的成员,计算序列长度等等 列表定义用[ ],字符串用’ ‘,元组用() 字符串和元组是不可变的,可变的只有列表!
python是从0开始的,然后用负数表示倒数。比如-1表示倒数第一个。
>>> nums = ['a', 2, 3, 4, 5] # 列表>>> nums[0]'a'>>> nums[-1] 5这个就是切切切,当然要制定切的左端和右端,最重要的一点是左闭右开,所以都是用正数表示的切的位置,直接大减小就是切出的序列的长度。
>>> numbers = [1, 2, 3, 4, 5, 6]>>> numbers[-3:-1] # 实际取出的是 numbers[-3], numbers[-2][4, 5]>>> numbers[-3:0] # 左边索引的元素比右边索引出现得晚,返回空序列[]>>> numbers = [1, 2, 3, 4, 5, 6, 7, 8]>>> numbers[-3:][6, 7, 8]>>> numbers[5:][6, 7, 8]# [:]可以复制整个序列这个有啥好说的啊,就是往序列中添加元素呗。直接“+”不就行了。
乘N就是加N次。
>>> [1, 2, 3] * 3[1, 2, 3, 1, 2, 3, 1, 2, 3]>>>'hehe'*3'hehehehehehe'检查某个值是否在序列中。
>>>'he' in 'hehh'True上面既然已经说了序列的通用操作,那么就说说针对列表有哪些常用的函数吧 - index - count - append - extend - insert - pop - remove - reverse - sort
index:就是看某个元素的索引呗。且只返回第一个该元素的索引,稍微想想也知道啊,不可能给你一大堆索引的吧,所以就返回第一个得了。
>>> Words = ['hello', 'world', 'you', 'me', 'he','meagain']>>> words.index('me')3count:略吧 append:末尾增加新的元素,由于list的元素类型可以是任意的,所以你可以随便append啊
>>>a = ['a',1,2]>>>a.append(['what',1])['a', 1, 2, ['what', 1]]extend: (⊙v⊙)嗯,扩展,想必也是类似append,但是发现没有,扩展并不是添加,所以它是: 将一个新列表的元素添加到原列表中
>>> a = [1, 2, 3]>>> b = [4, 5, 6]>>> a.extend(b)>>> a[1, 2, 3, 4, 5, 6]insert: insert(pos, value) 是将value添加到pos的位置。 pop:默认是移除最后一个,也可以移除指定index的元素。list.pop()或是list.pop(index) remove:list.remove(‘value’), 只移除第一个匹配的 reverse:反转
显然像这些extend,append,insert, pop, reverse, remove等都是在原序列上进行操作的。 sort是返回新的列表。默认从小到大升序排列。 list.sort(reverse=True)就降序了。 sorted就是在原列表上进行操作 你可能会觉得,啊啊,那我要进行制定方式进行排序呢。加key!
>>> s = ['ccc', 'a', 'bb', 'dddd']>>> s.sort(key=len) # 使用 len 作为键函数,根据元素长度排序>>> s['a', 'bb', 'ccc', 'dddd']显然,满足通用的序列操作。再次强调,只有列表可变啊啊啊!字符串是不可变的。所以不能给字符串赋值。 常用字符串方法 - find - split - join - strip - replace - translate - lower/upper
find: 查找子串呗。没找到就返回-1
>>> motto = "to be or not to be, that is a question">>> motto.find('be') # 返回 'b' 所在的位置,即 33>>> motto.find('be', 4) # 指定从起始位置开始找,找到的是第 2 个 'be'16>>> motto.find('be', 4, 7) # 指定起始位置和终点位置,没有找到,返回 -1-1split: 字符串切成序列 这个有意思啊,相当于字符串往列表转,而且可以指定切的分隔符。 显然默认空格作为分隔符啊
>>> '/user/bin/ssh'.split('/') # 使用 '/' 作为分隔符['', 'user', 'bin', 'ssh']>>> '1+2+3+4+5'.split('+') # 使用 '+' 作为分隔符['1', '2', '3', '4', '5']>>> 'that is a question'.split() # 没有提供分割符,默认使用所有空格作为分隔符['that', 'is', 'a', 'question']join: 可以说是split的逆方法吧
>>> '/'.join(['', 'user', 'bin', 'ssh'])'/user/bin/ssh'>>>>>> '+'.join(['1', '2', '3', '4', '5'])'1+2+3+4+5'>>> ' '.join(['that', 'is', 'a', 'question'])'that is a question'>>> ''.join(['h', 'e', 'll', 'o'])'hello'strip:去掉字符串左右两边的空格,或是指定的字符串
>>> ' hello world! '.strip() # 移除左右两侧空格'hello world!'>>> '%%% hello world!!! ####'.strip('%#') # 移除左右两侧的 '%' 或 '#'' hello world!!! '>>> '%%% hello world!!! ####'.strip('%# ') # 移除左右两侧的 '%' 或 '#' 或空格'hello world!!!'replace: 替换所有
>>> motto = 'To be or not To be, that is a question'>>> motto.replace('To', 'to') # 用 'to' 替换所有的 'To',返回了一个新的字符串'to be or not to be, that is a question'>>> motto # 原字符串保持不变'To be or not To be, that is a question'translate: 看名称就知道了啊,翻译翻译,当然是一个字一个字对应的。所以要用指定的翻译对应表,这开始有点扯了。
>>> from string import maketrans>>> table = maketrans('aeiou', '12345')>>> motto = 'to be or not to be, that is a question'>>> motto.translate(table)'t4 b2 4r n4t t4 b2, th1t 3s 1 q52st34n'>>> motto'to be or not to be, that is a question'>>> motto.translate(table, 'rqu') # 移除所有的 'r', 'q', 'u''t4 b2 4 n4t t4 b2, th1t 3s 1 2st34n'lower/upper: 略
不可变序列,用圆括号表示。
>>> a = (1, 2, 3) # a 是一个元组>>> a(1, 2, 3)>>> a[0] = 6 # 元组是不可变的,不能对它进行赋值操作Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: 'tuple' object does not support item assignment创建一个值的元组需要在值后面再加一个逗号,这个比较特殊,需要牢牢记住:
>>> a = (12,) # 在值后面再加一个逗号>>> a(12,)>>> type(a)<type 'tuple'>>>>>>> b = (12) # 只是使用括号括起来,而没有加逗号,不是元组,本质上是 b = 12>>> b12>>> type(b)<type 'int'>想想也是啊,因为元组是用圆括号定义的啊,如果只有一个值的话,那么不加逗号不就成为了数了啊。 元组不可变,所以没有append,extend,sort等方法。
总说:字典是映射类型,有key和value构成,显然key要求是不可变类型,所以只能是数字,字符串和元组。
另一种遍历,如果遍历时要删除字典的某一项,那么要改改遍历方法:
for key in d.keys(): # python3的时候改成list(d.keys()) if key == 'name' del d[key]推荐的遍历方法 使用iteritems函数。for k,v in d.iteritems(): print '%s: %s' % (k,v)判断键是否在字典 一样的啊,用in呗。clear:
>>> d1 = {}>>> d2 = d1>>> d2['name'] = 'ethan'>>> d1{'name': 'ethan'}>>> d2{'name': 'ethan'}>>> d1.clear() # d1 清空之后,d2 也为空>>> d1{}>>> d2{}copy: 这个比较特殊诡异。竟然是浅复制。。 copy 方法实现的是浅复制(shallow copy)。它具有以下特点:
对可变对象的修改保持同步;对不可变对象的修改保持独立 ;# name 的值是不可变对象,books 的值是可变对象,再读一遍,是看“值”是什么类型!!>>> d1 = {'name': 'ethan', 'books': ['book1', 'book2', 'book3']}>>> d2 = d1.copy()>>> d2['name'] = 'peter' # d2 对不可变对象的修改不会改变 d1>>> d2{'books': ['book1', 'book2', 'book3'], 'name': 'peter'}>>> d1{'books': ['book1', 'book2', 'book3'], 'name': 'ethan'}>>> d2['books'].remove('book2') # d2 对可变对象的修改会影响 d1>>> d2{'books': ['book1', 'book3'], 'name': 'peter'}>>> d1{'books': ['book1', 'book3'], 'name': 'ethan'}>>> d1['books'].remove('book3') # d1 对可变对象的修改会影响 d2>>> d1{'books': ['book1'], 'name': 'ethan'}>>> d2{'books': ['book1'], 'name': 'peter'}深复制就用copy模块的deepcopy。
get: 就是防止你随便访问不存在的项产生KeyError。用get就返回空
>>> d = {}>>> d['name']Traceback (most recent call last): File "<stdin>", line 1, in <module>KeyError: 'name'>>> print d.get('name')Nonesetdefault:就是设定一个默认的键值对,如果原字典已经设置了,那么就不会采用默认的键值对,如果原子典没有,那么显然会添上默认的键值对。
>>> d = {}>>> d.setdefault('name', 'ethan') # 返回设定的默认值 'ethan''ethan'>>> d # d 被更新{'name': 'ethan'}>>> d['age'] = 20>>> d{'age': 20, 'name': 'ethan'}>>> d.setdefault('age', 18) # age 已存在,返回已有的值,不会更新字典20>>> d{'age': 20, 'name': 'ethan'}update: 将一个字典添加到原字典,如果存在相同的键则会进行覆盖。
items 方法将所有的字典项以列表形式返回,这些列表项的每一项都来自于(键,值)。我们也经常使用这个方法来对字典进行遍历。 iteritems 的作用大致相同,但会返回一个迭代器对象而不是列表,同样,我们也可以使用这个方法来对字典进行遍历,而且这也是推荐的做法. 推荐的做法在前面已经阐述。
keys 方法将字典的键以列表形式返回,iterkeys 则返回针对键的迭代器。 values 方法将字典的值以列表形式返回,itervalues 则返回针对值的迭代器。
移除字典中某个键值对,并返回给定的键的值 popitem随机移除某个键值对
就是说一个列表中有很多个字典,然后你要对这些字典进行排序。
students = [ {'name': 'john', 'score': 'B', 'age': 15}, {'name': 'jane', 'score': 'A', 'age': 12}, {'name': 'dave', 'score': 'B', 'age': 10}, {'name': 'ethan', 'score': 'C', 'age': 20}, {'name': 'peter', 'score': 'B', 'age': 20}, {'name': 'mike', 'score': 'C', 'age': 16}]按score从小到大排序>>> sorted(students, key=lambda stu: stu['score'])#返回的字典的键值对先后顺序与下面不一样。然而并没有什么关系,为了简便,不改了。[{'age': 12, 'name': 'jane', 'score': 'A'}, {'age': 15, 'name': 'john', 'score': 'B'}, {'age': 10, 'name': 'dave', 'score': 'B'}, {'age': 20, 'name': 'peter', 'score': 'B'}, {'age': 20, 'name': 'ethan', 'score': 'C'}, {'age': 16, 'name': 'mike', 'score': 'C'}]按 score 从大到小排序>>> sorted(students, key=lambda stu: stu['score'], reverse=True) # reverse 参数按 score 从小到大,再按 age 从小到大sorted(students, key=lambda stu: (stu['score'], stu['age']))按 score 从小到大,再按 age 从大到小sorted(students, key=lambda stu: (stu['score'], -stu['age']))一句话,集合也用{ }, 它是一组key的集合,没有value。特性就是key不能重复!
>>> se = {'a',1}>>> seset(['a', 1])遍历 仍旧是for e in s: 结构呗添加 add() 方法>>> s = {'a', 'b', 'c', 'a', 'd', 'b'}>>> s.add('e') #没效果>>> sset(['a', 'c', 'b', 'e', 'd'])>>> s.add(4)>>> sset(['a', 'c', 'b', 4, 'd', 'e'])删除 remove()子集判断 set.issubset(subset)分别是 & | -
>>> s1 = {1, 2, 3, 4, 5, 6}>>> s2 = {3, 6, 9, 10, 12}>>> s3 = {2, 3, 4}>>> s1 & s2 # 交集set([3, 6])>>> s1 | s2 # 并集set([1, 2, 3, 4, 5, 6, 9, 10, 12])>>> s1 - s2 # 差集set([1, 2, 4, 5])新闻热点
疑难解答