一、Python变量与数据类型
整数:
浮点数:浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,比如,1.23x10^9和12.3x10^8是相等的。
Python整数运算结果仍然是整数,浮点数运算结果仍然是浮点数。
字符串:以’ ‘或” “括起来的任意文本
布尔值:True/ False
布尔运算:and–与运算;or–或运算; not–非运算
空值:是Python里一个特殊的值,用None表示。None不能理解为0,因为0是有意义的,而None是一个特殊的空值
变量:变量名必须是大小写英文、数字和下划线(_)的组合,且不能用数字开头
在Python中,等号=是赋值语句,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,且可以是不同类型的变量,如:
a = 123 # a是整数。代码中注释以#开头
print a
a = 'imooc' # a变为字符串
print a
这种变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言(如Java)。
理解变量在计算机内存中的表示也非常重要。当我们写:a = ‘ABC’时,Python解释器干了两件事情:
1. 在内存中创建了一个’ABC’的字符串;
2. 在内存中创建了一个名为a的变量,并把它指向’ABC’。
也可以把一个变量a赋值给另一个变量b(b=a),这个操作实际上是把变量b指向变量a所指向的数据,例如下面的代码:
a = 'ABC'
b = a
a = 'XYZ'
print b
最后一行打印出变量b的内容到底是’ABC’呢还是’XYZ’?如果从数学意义上理解,就会错误地得出b和a相同,也应该是’XYZ’,但实际上b的值是’ABC’,让我们一行一行地执行代码,就可以看到到底发生了什么事:
执行a = ‘ABC’,解释器创建了字符串 ‘ABC’和变量 a,并把a指向 ‘ABC’;
执行b = a,解释器创建了变量 b,并把b指向 a 指向的字符串’ABC’;
执行a = ‘XYZ’,解释器创建了字符串’XYZ’,并把a的指向改为’XYZ’,但b并没有更改;
所以,最后打印变量b的结果自然是’ABC’了。
要表示字符串 Bob said “I’m OK”.
由于 ’ 和 ” 会引起歧义,因此,我们在它前面插入转义字符\表示这是一个普通字符,不代表字符串的起始,因此,这个字符串又可以表示为:
'Bob said \"I\'m OK\".'
注意:转义字符 \ 不计入字符串的内容中。
常用的转义字符还有:
\n 表示换行
\t 表示一个制表符
\\ 表示 \ 字符本身
raw 字符串:避免多次转义
如果一个字符串包含很多需要转义的字符,对每一个字符都进行转义会很麻烦。为了避免这种情况,我们可以在字符串前面加个前缀 r ,表示这是一个 raw 字符串,里面的字符就不需要转义了。如: r’(~_~)/ (~_~)/’
但是r’…’表示法不能表示多行字符串,也不能表示包含’和 “的字符串。如果要表示多行字符串,可以用”’…”’表示:
还可以在多行字符串前面添加 r ,把这个多行字符串也变成一个raw字符串:
r”’Python is created by “Guido”.
It is free and easy to learn.
Let’s start learn Python in imooc!”’
Unicode字符串:u ’ ’ #添加对中文的支持,否则出现乱码
二、List与Tuple类型
2.1 list(列表):是一种有序的集合,可以随时添加和删除其中的元素。直接用 [ ] 把list的所有元素都括起来,就是一个list对象。
由于Python是动态语言,所以list中包含的元素并不要求都必须是同一种数据类型。如:
L = [‘Michael’, 100, True]
L[0]为第一个元素,L[2]第3个元素。L[3]就会越界。
倒序索引:
L[-1]为最后一个元素,L[-2]为倒数第二个元素,以此类推。注意,L[-4]就会越界。
List添加元素:
append():将新元素添加到List的尾部:
L.append(‘Paul’) –> L = [‘Michael’, 100, True,’Paul’]
insert()方法,将元素添加到指定位置,该方法接收2个参数。如L.insert(0,’Paul’)–将’Paul’添加到索引为0(也就是第一个)位置。
List删除元素:
pop():删掉list的最后一个元素,并且它还返回这个元素。所以L.pop()会返回’Paul’。
L.pop(index):删除指定位置的元素。如L.pop(2)删除True。
List替换元素
删L = [‘Adam’, ‘Lisa’, ‘Bart’],若要把Bart删掉,再把Paul添加进来,操作为:
L[2] = ‘Paul’ 或者 L[-1] = ‘Paul’
List大小:len(L)
对list进行切片(Slice)操作
L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2这3个元素。
如果第一个索引是0,还可以省略: L[:3]
只用一个 : ,表示从头到尾: L[:]。L[:]实际上复制出了一个新list。
三个参数:L[::N] 第三个参数表示每N个取一个。如上面的 L[::2] 会每两个元素取出一个来,即隔一个取一个。
把list换成tuple,切片操作完全相同,只是切片的结果也变成了tuple。
倒序切片:
倒数第一个元素的索引是-1。倒序切片包含起始索引,不包含结束索引。
对字符串s切片(相当于字符串截取)
s[0]:第一个字符
s[1:]第一个字符后的子串
s.upper():字符串全部转为大写
2.2 tuple( 元组):另一种有序的列表。tuple 和 list 非常类似,区别是:tuple一旦创建完毕,就不能修改。因此,tuple没有 append()方法,也没有insert()和pop()方法。
tuple的索引也是与list类似,也是t[0]、t[-1]
创建tuple和创建list唯一不同之处是用( )替代了[ ]。
*定义 0 个元素的 tuple,也就是空tuple,直接用 ()表示:t = ()
*定义 单 个元素的 tuple时,要多加一个逗号“,”避免歧义,因为()既可以表示tuple,又可以作为括号表示 运算时的优先级。否则t = (1),t为整数1,而不是元组。
*定义多元素 tuple时 加不加这个额外的“,”效果是一样的。
“可变”的tuple:
t = ('a', 'b', ['A', 'B'])
注意到 t 有 3 个元素:’a’,’b’和一个list:[‘A’, ‘B’]。list作为一个整体是tuple的第3个元素。list对象可以通过 t[2] 拿到: L = t[2]
然后,我们把list的两个元素改一改:
L[0] = 'X'
L[1] = 'Y'
我们先看看定义的时候tuple包含的3个元素:
当我们把list的元素’A’和’B’修改为’X’和’Y’后,tuple变为:
表面上看,tuple的元素确实变了,但其实变的不是 tuple 的元素,而是list的元素。
tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向’a’,就不能改成指向’b’,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!
理解了“指向不变”后,要创建一个内容也不变的tuple怎么做?那就必须保证tuple的每一个元素本身也不能变。
三、 条件判断和循环 (每个语句后都有冒号 : )
Python代码有缩进规则。具有相同缩进的代码被视为代码块
缩进严格按照Python的习惯写法:4个空格,不要使用Tab,更不要混合Tab和空格
if
else
elif 等价于 else if
for … in … :
while
退出循环:break退出当前循环;
continue跳过后续循环代码,继续下一次循环。
四、字典dict
如:
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59}
花括号 {} 表示这是一个dict,然后按照 key: value, 写出来即可。最后一个 key: value 的逗号可以省略。
len(d) ==3 计算字典大小
list 必须使用索引返回对应的元素,而dict使用key:d[‘Adam’] –> 95
而:print d[‘Paul’] –> KeyError: ‘Paul’
通过 key 访问 dict 的value,只要 key 存在,dict就返回对应的value。如果key不存在,会直接报错:KeyError。
要避免 KeyError 发生,有两个办法:
一是先判断一下 key 是否存在,用 in 操作符:
if ‘Paul’ in d:
print d[‘Paul’]
如果 ‘Paul’ 不存在,if语句判断为False,自然不会执行 print d[‘Paul’] ,从而避免了错误。
二是使用dict本身提供的一个 get (key)方法,在Key不存在的时候,返回None:
print d.get('Bart')
-->59
print d.get('Paul')
-->None
dict的特点:
1、查找速度快。无论dict有10个元素还是10万个元素,查找速度都一样。而list的查找速度随着元素增加而下降。
不过dict的查找速度快不是没有代价的,dict的缺点是占用内存大,还会浪费很多内容,list正好相反,占用内存小,但是查找速度慢。
由于dict是按 key 查找,所以,在一个dict中,key不能重复。
2、key-value对无序。
3、 key 不可变。Python的基本类型如字符串、整数、浮点数都是不可变的,都可以作为 key。但是list是可变的,就不能作为 key。最常用的key还是字符串,因为用起来最方便。
dict的更新:用赋值语句
如:d[‘Paul’] = 72
key 已经存在,则赋值会用新的 value 替换掉原来的 value:
dict的遍历:
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
for key in d:
print key + ':', d[key] #d[key] :值
五、set:无序
创建 set 的方式是调用 set() 并传入一个 list,list的元素将作为set的元素:
s = set(['A', 'B', 'C'])
访问set: ‘A’ in s –>输出:True
遍历访问set与list和dict类似。
set的内部结构和dict很像,唯一区别是不存储value,因此,判断一个元素是否在set中速度很快。
set存储的元素和dict的key类似,必须是不变对象,因此,任何可变对象是不能放入set中的。
更新set:添加、删除
添加:add()
删除:remove()。
如果删除的元素不存在set中,remove()会报错;所以用add()可以直接添加,而remove()前需要判断。
六、函数
定义一个函数要使用 def 语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用 return 语句返回。
如果没有return语句,函数执行完毕后也会返回结果,只是结果为 None。
return None可以简写为return。
函数的多返回值:其实就是返回一个tuple,只是写起了方便
默认参数:默认参数的作用是简化调用,你只需要把必须的参数传进去。但是在需要的时候,又可以传入额外的参数来覆盖默认参数值。
定义一个计算 x 的N次方的函数:
def power(x, n):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
假设计算平方的次数最多,我们就可以把 n 的默认值设定为 2:
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
这样一来,计算平方就不需要传入两个参数了:
power(5)
-->25
可变参数函数:def f(*args):
Python解释器会把传入的一组参数组装成一个tuple传递给可变参数,因此,在函数内部,把变量 args 看成一个 tuple 就好了。
七、迭代(for循环)
迭代操作就是对于一个集合,无论该集合是有序还是无序,用 for 循环总是可以依次取出集合的每一个元素。
注意: 集合是指包含一组元素的数据结构,已经介绍的包括:
1. 有序集合:list,tuple,str和unicode;
2. 无序集合:set
3. 无序集合并且具有 key-value 对:dict
Python中,迭代永远是取出元素本身,而非元素的索引。
有时候,想要在for循环中拿到索引,可以用 enumerate() 函数:
L = ['Adam', 'Lisa', 'Bart', 'Paul']
for index, name in enumerate(L):
... print index, '-', name
...
0 - Adam
1 - Lisa
2 - Bart
3 - Paul
使用 enumerate() 函数,我们可以在for循环中同时绑定索引index和元素name。但是,这不是 enumerate() 的特殊语法。实际上,enumerate() 函数把:[‘Adam’, ‘Lisa’, ‘Bart’, ‘Paul’]
变成了类似:[(0, ‘Adam’), (1, ‘Lisa’), (2, ‘Bart’), (3, ‘Paul’)]
因此,迭代的每一个元素实际上是一个tuple:
for t in enumerate(L):
index = t[0]
name = t[1]
print index, '-', name
如果我们知道每个tuple元素都包含两个元素,for循环又可以进一步简写为:
for index, name in enumerate(L):
print index, '-', name
这样不但代码更简单,而且还少了两条赋值语句。
可见,索引迭代也不是真的按索引访问,而是由 enumerate() 函数自动把每个元素变成 (index, element) 这样的tuple,再迭代,就同时获得了索引和元素本身。
迭代dict的value:
方法1:dict对象的values()方。把dict转换成一个包含所有value的list
方法2:dict的itervalues()方法。不会转换,它会在迭代过程中依次从 dict 中取出 value,所以 itervalues() 方法比 values() 方法节省了生成 list 所需的内存。
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.values()
--> [85, 95, 59]
print d.itervalues()
--><dictionary-valueiterator object at 0x106adbb50>
for v in d.itervalues(): # for v in d.values():
print v
--> 85
--> 95
--> 59
迭代是一种抽象的数据操作,它不对迭代对象内部的数据有任何要求。
迭代dict的key和value:同时迭代key和value
dict对象的items()方法把dict对象转换成了包含tuple的list,对该list进行迭代,就可以同时获取key和value
for key, value in d.items():
和 values() 有一个 itervalues() 类似, items() 也有一个对应的 iteritems()。iteritems() 不把dict转换成list,而是在迭代过程中不断给出 tuple,所以, iteritems() 不占用额外的内存。
八、列表生成式
生成列表:
要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],可以用range(1, 11):
range(1, 11)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
但如果要生成[1x1, 2x2, 3x3, …, 10x10]怎么做?方法一是循环:
L = []
for x in range(1, 11):
... L.append(x * x)
...
L
-->[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
但是循环太繁琐,而Python特有的列表生成式则可以用一行语句代替循环生成上面的list:
[x * x for x in range(1, 11)]
利用列表生成式,可以以非常简洁的代码生成 list。
写列表生成式时,把要生成的元素 x * x 放到前面,后面跟 for 循环,就可以把list创建出来,十分有用,多写几次,很快就可以熟悉这种语法。
复杂的列表生成式中可以嵌入html
条件过滤:列表生成式的 for 循环后面还可以加上 if 判断。
[x * x for x in range(1, 11) if x%2==0] #只生成偶数的平方
多层表达式:for循环可以嵌套,因此,在列表生成式中,也可以用多层 for 循环来生成列表。
对于字符串 ‘ABC’ 和 ‘123’,可以使用两层循环,生成全排列:
[m + n for m in 'ABC' for n in '123']
-->['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
翻译成循环代码就像下面这样:
L = []
for m in 'ABC':
for n in '123':
L.append(m + n)