前言
打算写一系列文章来记录自己学习 Python 3 的点滴;本篇将会重点介绍 python 的最基础部分知识,字符串、编码、队列等等;
本文为作者的原创作品,转载需注明出处;
数据类型和变量
字符串
特殊使用方式
Python 允许使用 '''...'''
的格式表示多行的内容;替代重复写多个\t
换行符的方式
1 | >>> print('''line1 |
格式化输出
来看一个最简单的格式化输出,
1 | >> print('hello %s' % 'world') |
%s 是一个占位符,使用 ‘world’ 来进行填充,除了 %s 还有如下的占位符
1 | %s 字符串 (采用str()的显示) |
所以,我们不仅可以对自己进行格式化输出,同样可以对数字进行格式化输出,比如,
1 | >> print('hello %s, this is the year %d' % ('world', 2018)) |
布尔值
Python 布尔值的写法为 True
、False
;注意的是,第一个字母大写;
空值
Python 的空值用None
表示;该值相当于 Java 中的 Null
;
常量
Python 中约定大写的变量名为常量,比如
1 | PI = 3.14159265359 |
不过实际上,它仍然是一个变量;
弱类型
Python 的变量是弱类型,也就是说变量的类型是在运行时刻才被决定的;比如,
1 | a = 123 # a是整数 |
类型转换
1 | >>> s = "100" |
可以看到,python 在将一个 str 类型与 int 类型比对的时候,不会像赋值那样,自动的判断和赋值类型,这里是会报错的;所以,在比较之前,我们需要对其进行类型转换;
1 | >>> int(s) > 99 |
通过int()
方法进行类型转换即可;其它的类型转换如下所述
1 | >>> float('12.34') |
list 和 tuple
list
python 的一种内置类型,表示一个有序列表,可以对其修改该,增加或者删除元素;
比如,我们有如下的列表结合,
1 | >>> classmates = ['Michael', 'Bob', 'Tracy'] |
长度
1 | >>> len(classmates) |
访问元素
两种访问方式,
正序访问,1
2
3
4
5
6
7
8
9
10>>> classmates[0]
'Michael'
>>> classmates[1]
'Bob'
>>> classmates[2]
'Tracy'
>>> classmates[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
倒序访问,1
2
3
4
5
6
7
8>>> classmates[-2]
'Bob'
>>> classmates[-3]
'Michael'
>>> classmates[-4]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
追加
通过调用append
方法将元素追加到队列的末尾;1
2
3>>> classmates.append('Adam')
>>> classmates
['Michael', 'Bob', 'Tracy', 'Adam']
插入
通过insert
方法插入到指定位置,1
2
3>>> classmates.insert(1, 'Jack')
>>> classmates
['Michael', 'Jack', 'Bob', 'Tracy', 'Adam']
删除并返回
通过pop()
删除并返回队列末尾的元素
1 | >>> classmates.pop() |
通过pop(n)
删除并返回指定坐标的元素
1 | >>> classmates.pop(1) |
替换
1 | >>> classmates[1] = 'Sarah' |
多种数据类型
list 中的元素可以由多种其它数据类型组成;
1 | >>> L = ['Apple', 123, True] |
同时,list 中的某个元素还可以是一个 list,也就是说,可以嵌套另外一个 list;
1 | >>> s = ['python', 'java', ['asp', 'php'], 'scheme'] |
排序
可以直接调用 list 的内置方法,对其进行排序;1
2
3
4>>> s = ['python', 'java', 'php', 'scheme']
>>> s.sort()
>>> s
['java', 'php', 'python', 'scheme']
tuple
也是一种有序列表,叫做元组
;与 list 非常的类似,但,tuple 一旦初始化以后,就不允许修改该了;
1 | >>> classmates = ('Michael', 'Bob', 'Tracy') |
这样的话,也就是说 classmates 这个 tuple 元组就不再允许被修改该了,也就是说,没有对应的增、删、改等方法了,也就是没有了对应的 insert、pop 等方法了;注意,元组的定义,使用的是双括号
,而 list 使用的是方括号
;
要注意的是,如果你要定义只有一个元素的 tuple,1
2
3>>> t = (1)
>>> t
1
可见,这里输出的并不是一个 tuple,而是一个数字 1;因为这样写会引起歧义,这里会被解释器识别为数学公式中的括号,而这里,python 将会把它识别为数学公式中的括号,而直接忽略掉了,所以输出的就是一个数字;所以,python 规定,如果只有一个元素的 tuple,定义的时候,为了避免歧义,必须加上一个,
的后缀符号,
1 | >>> t = (1,) |
tuple 中可以包含 list 元素,且该 list 仍然是可变的1
2
3
4
5>>> t = ('a', 'b', ['A', 'B'])
>>> t[2][0] = 'X'
>>> t[2][1] = 'Y'
>>> t
('a', 'b', ['X', 'Y'])
当然原因也非常的简单,就是因为 list 对象本身的特性所决定的;
条件判断
通过几个例子来看看 IF ELSE 在 python 中的写法,
IF…ELSE1
2
3
4
5
6
7age = 3
if age >= 18:
print('your age is', age)
print('adult')
else:
print('your age is', age)
print('teenager')
IF…ELSEIF1
2
3
4
5
6
7age = 3
if age >= 18:
print('adult')
elif age >= 6:
print('teenager')
else:
print('kid')
要特别注意上面的写法,每一次条件语句后面都会跟一个:
;
IF X1
2if x:
print('True')
只要x
是非零数值、非空字符串、非空 list 等,就判断为True
,否则为False
。
再来看一下如何在 if 判断语句中表示 and 和 or 的逻辑,
1 | age = 3 |
for 语句表达式
网上已经有很多 for 的基本用法,比如 for for,for else 等等,基本用法可以参考官方的教程 https://wiki.python.org/moin/ForLoop 如果笔者在这里还是照本宣科,将一些 for 语句的基本用法,就没有什么意思了,我们来看看教科书上不曾写到的一些进阶的用法,for 语句可以用来构造 Dict、Set、List 实例,下面笔者一一来举例
for 语句用来构造 Set 实例
比如,我们可以使用 for 语句来直接构造 1 到 10 的一个 Set1
2
3for n in range(1,11)} set = {n
set
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}注意,表达式的写法 n for n in range(1,11),其中第一个 n 表示当前循环的返回值,这样循环 10 次便构造了包含 10 个数字的 Set 实例;
for 语句用来构造 List 实例
同样,我们可以使用上面的方式来构造一个 List 实例,1
2
3for n in range(1,11)] list = [n
list
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]for 语句用来构造 Dict 实例
这是最有趣也是最有用的一种方式了,看一个例子,1
2
3
4
5
6
7
8
9
10
11
12
13
142, n): n for n in range(1,11)} results = {pow(
results
{
2: 1,
4: 2,
8: 3,
16: 4,
32: 5,
64: 6,
128: 7,
256: 8,
512: 9,
1024: 10
}这里要注意 Dict 中左边表达式 pow(2, n) 中的 n 既是 for 循环中 n 的当前值;从输出结果中可以看到,我们自动的将 pow 的结果和输入值构建了一个 Dict 对象,这样,我们便快速的构建了一种键值对的数据模型;有意思吗?我的数学能力很好,1024 我可以直接推导出是 10,建立这种映射关系有何用?试想,如果我们计算的是 pow(111,n) 呢?或者是对某个质数计算 pow 呢?使用 for 循环构建 Dict 实例的方式可以让我们快速的构建出这种 Dict 数据关系,仅需一行代码;
读者可能会问,这样做到底有多大意思?笔者想说的是,这样做很有意思,可以极大的简化我们的代码,10 行代码可以并做一行,看下面这例子,
1 | import concurrent.futures |
这是一个 Thread Pool 的例子,通过多线程的方式同时下载 URLS 中的链接,看代码第 18 行,1
future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
仅通过一行代码,我便建立了不同的 future 对象与相关 URL 的键值模型的的 Dict 对象;
dict 和 set
dict
Python 的内置的字典;全称是 Dictionary,在其它的语言中称为 map,使用键值对(Key-Value)进行存储,因为是通过 Hash(Key) 的方式来存取 Value 值,所以它的执行效率非常的块,典型的以空间换时间的方式;
创建
创建一个字典的方式有好几种方式,下面以创建一个学生的成绩字典的例子来分别进行演示
第一种方式,
1 | 'Michael': 95, 'Bob': 75, 'Tracy': 85} d = { |
第二种方式,
1 | 95, Bob = 75, Tracy = 85) d = dict( Michael = |
第三种方式,
1 | 'Michael': 95, 'Bob': 75, 'Tracy': 85}) d = dict({ |
第四种方式,
1 | 'Michael', 95], ['Bob', 75], ['Tracy', 85] ] ) d = dict( [ [ |
追加
方式一
1
2
3>>> d['Adam'] = 67
>>> d['Adam']
67这样,我们就新增了一个字典键值对
'Admin':67
多次对同一个键进行追加,会覆盖之前的 Value;
1
2
3
4
5
6>>> d['Jack'] = 90
>>> d['Jack']
90
>>> d['Jack'] = 88
>>> d['Jack']
88方式二、通过 update() 方法,
新增1
2
3
4>>> x = {1:2}
>>> x.update({3:4})
>>> print(x)
{1: 2, 3: 4}注意,通过 update 方法给一个空的 dict 对象新增值也是可以的,
1
2
3
4>>> x = {}
>>> x.update({1:2})
>>> print(x)
{1: 2}更新
1
2
3>>> x.update({3:6})
>>> print(x)
{1: 2, 3: 6}
取值
1 | >>> d['Jack'] |
如果取到一个不存在的值,将会报错,
1 | >>> d['Thomas'] |
所以,为了避免这样的错误,在取值之前可以做一些判断,可以通过in
来判断其键是否存在;
1 | >>> 'Thomas' in d |
另外,可以通过get
方法来进行取值,这样如果该值不存在,将会返回None
,或者指定一个自己期望的值;
1 | >>> d.get('Thomas') |
第一个返回的是None
,Python 默认不显示,第二个返回的就是自己指定的值 -1
;
删除
通过pop(key)
方法,将对应的 key 和 value 一并从 dict 中删除;
1 | >>> d.pop('Bob') |
key 必须是不可变的
因为 Dict 是根据 hash(Key) 来存取 value 的,所以有一个非常重要的前提就是,Key 是不可变的元素;Python 中,字符串、数字、Tuple 对象都是不可变的,因此非常适合作为 Dict 的 Key,而 List 是可变元素,因此,在 Python 中是强制规定其不能作为 Key 的,若作为 key,编译的时候就会出错;
1 | >>> key = [1, 2, 3] |
set
set 类似于其实也是一个 Dict,唯一区别是,set 只存储 Keys,不存储 Values;既然是一个 Dict,那么就要求所存储的 Keys 是不可变元素,这一点可以从创建小节中得到论证;
创建
在创建 set 集合的时候,要求传入一个 list 集合作为参数;
1 | >>> s = set([1, 2, 3]) |
要求作为参数的 list 不能有可变元素,比如
1 | >>> s = set([1, [2, 3], 4]) |
可见,list 中的第二个元素 [2, 3] 是一个 list,是一个可变元素,所以在创建的时候,报错;这也就间接的证明了,set 实际上是一个 dict;
重复元素将会被自动的去重;
1 | >>> s = set([1, 1, 2, 2, 3, 3]) |
追加
通过方法add(key)
的方式追加元素到 set 中;
1 | >>> s.add(4) |
可以看到,重复元素将会被自动过滤;
删除
通过 remove(key)
的方法进行删除;1
2
3>>> s.remove(4)
>>> s
{1, 2, 3}
排序
在创建和添加 set 的时候,会自动的根据 key 值进行排序;
1 | >>> s = set([ 8, 3, 2, 1, 9, 3, 4 ] ) |
可以看到,无论是在新建还是追加的过程中,set 集合都会自动的将 keys 进行排序;
交集和并集
我们有两个 set 集合,1
2>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
交集&
1
2>>> s1 & s2
{2, 3}
并集|
1
2>>> s1 | s2
{1, 2, 3, 4}
进制转换
有时候,在处理底层字符编码的时候,我们经常需要在二进制、八进制、十进制和十六进制之间进行转换;
转换为十进制
如何将其它进制的数据转换为十进制;通过方法int(value, format)
,参数 value 是其它进制的数据,参数 format 表示当前数字的进制;
比如,我们要将十六进制转换为十进制,1
2>>> int('e4b8', 16)
58552
将二进制转换为十进制,1
2>>> int('11010011111', 2)
1695
转换为八进制
通过 oct(value)
方法将 value 转换为对应的八进制;注意,这里有一个限制,就是只能转换十进制的数据,也就是说,输入的 value 必须是十进制,而且也只有这样一个方法可用,oct(value, format)
不存在的;
1 | >>> oct(58552) |
转换为十六进制
通过 hex(value)
方法将 value 转换为对应的十六进制,同转换为八进制,这里的参数 value 也必须是十进制数据;
1 | >>> hex(58552) |
十进制转换为二进制
通过bin(value)
方法将 value 转换为对应的二进制,同转换为八进制,这里的参数 value 也必须是十进制数据;
1 | >>> bin(1695) |
Reference
upgrade from python 2 to 3: https://www.macobserver.com/tmo/article/how-to-upgrade-your-mac-to-python-3
python 3 tutorial: https://docs.python.org/3/tutorial/index.html
python 3: http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
dive into python3: http://www.diveintopython3.net/
python yield: https://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/index.html
http://www.liaoxuefeng.com/