变量和数据类型
变量
变量在计算机内存中的表示非常重要。当我们写:a = ‘ABC’时,Python解释器干了两件事情:
1. 在内存中创建了一个’ABC’的字符串;
2. 在内存中创建了一个名为a的变量,并把它指向’ABC’。
也可以把一个变量a赋值给另一个变量b,这个操作实际上是把变量b指向变量a所指向的数据,而不是把变量b指向变量a。
字符串
1.字符串用”“或者”表示;
2.当字符串中有”时用”表示,当字符串中有’时用”“表示;
3.当字符串中既有’又有”“时,使用转义字符\
例如,’Bob said \”I\’m OK\”.’
1.为了减少转义字符的不方便,可以用raw字符串来解决这个问题,在要字符串前加r就不需要转义字符了:r’字符串内容’
例如,
r'\(~_~)/ \(~_~)/'
2.但是上述方式不能表示多行字符串和包含’和”的字符串,要表示这两种可以用
'''Line 1
Line 2
Line 3'''
来表示。
也可以把这种多行字符串变成raw字符串:
r'''Line1
Line2
Line3'''
1.为了能正常显示中文,在字符串前加u,例如:
u '中文'
u'''第一行
第二行'''
2.raw字符串仍然成立
ur'''"第一行"
第二行'''
3.用notepad++编写代码时,出现错误UnicodeDecodeError,解决办法在第一行添加:# -- coding: utf-8 --
布尔类型
1.Python把0、空字符串”、None都看成False,其他数值和非空字符串都看成True
2.Python的短路计算:Python解释器在做布尔运算时,只要能提前确定计算结果,它就不会往后算了,直接返回结果。
(1)在计算 a and b 时,如果 a 是 False,则根据与运算法则,整个结果必定为 False,因此返回 a;如果 a 是 True,则整个计算结果必定取决与 b,因此返回 b。
(2)在计算 a or b 时,如果 a 是 True,则根据或运算法则,整个计算结果必定为 True,因此返回 a;如果 a 是 False,则整个计算结果必定取决于 b,因此返回 b。
3.理解
a = True
print a and ‘a=T’ or ‘a=F’
的结果是字符串’a=T’
List类型
创建list:Python是动态语言,所以list中包含数据的类型可以不同。
>>> classmates = ['Michael', 'Bob', 'Tracy']
>>> classmates
['Michael', 'Bob', 'Tracy']
空list:
>>> empty_list = []
按照索引访问list:L[0],L[1],L[2],…,L[-3],L[-2],L[-1]
list添加新元素:
(1)L.append(新元素)总把新元素添加到list末尾
(2)L.insert(i,新元素)把新元素添加到list的索引号为i的位置
从list中删除元素:
(1)L.pop():删除list中最后一个元素并且返回这个被删除的元素
(2)L.pop(i):删除list中索引为i的元素并返回这个被删除的元素
替换元素:
L[i]=新元素
把list中索引为i的元素用新元素替换
tuple类型
创建tuple:创建tuple和创建list的唯一不同之处就是用()代替了[]
>>> t = ('Adam', 'Lisa', 'Bart')
tuple可以包含0个元素:
>>> t=()
>>> print t
>>> ()
tuple也可以包含1个元素(必须加一个逗号,不然不表示元组):
>>> t=(1,)
>>> print t
>>> (1,)
访问tuple元素的方式和list一模一样:t[0],t[1],…,t[-1]
tuple和list的不同之处:tuple一旦创建完毕就不能修改了,所以tuple没有append()、insert()和pop()方法,可以访问tuple中的元素,但是不能给元素赋新值!tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向’a’,就不能改成指向’b’,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!
条件判断和循环
if条件判断
if 判断条件:
代码块
elif 判断条件:
代码块
else:
代码块
if语句的判断条件不用括号括起来,后面加冒号表示代码块开始,代码块要缩进4个字符(必须是4个空格,不能是Tab键)表示属于此部分代码块。
for循环
L = ['Adam', 'Lisa', 'Bart']
for name in L:
print name
tips:
1.注意代码块的缩进
2.依次取出list中每一个元素,并把元素赋值给name,然后执行for循环的代码块
while循环
N = 10
x = 0
while x < N:
print x
x = x + 1
while循环根据循环条件判断循环是否结束,只有循环条件为真才会执行代码块的内容。
使用for或者while循环时,如果要在循环体内直接退出循环使用break语句
sum = 0
x = 1
while True:
sum = sum + x
x = x + 1
if x > 100:
break
print sum
关于以前不理解的地方:上面例子中的break不是退出if语句块,而是退出while循环的语句块,break是用来退出循环(for和while循环)的,if不是循环。
在循环(还是考虑循环)中,用continue语句表示跳过后续循环代码,继续下一次循环。
for x in L:
if x < 60:
continue
sum = sum + x
字符串连接和数字连接输出
x='hello,'
y='world'
print x,y
print x+y
x=1
y=2
print x,y
print x+y
输出结果为:
hello, world
hello,world
1 2
3
dict类型
构建dict:用{}表示(看到{}就代表是dict),dict通过key来查找value
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
len(d)=3,因为一个key-value算一个。
访问dict
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
(1)使用d[key]的方式
>>>print d['Adam']
95
与list的不同之处:list必须使用索引访问,dict使用key访问
(2)使用dict本身提供的get方法,在key不存在的时候返回None
>>> print d.get('Bart')
59
>>> print d.get('Paul')
None
dict的特点:
(1)dict查找速度快(无论dict有多少个元素查找速度都相同),占用内存大;list查找速度慢(list查找速度随元素个数增加而下降),占用内存小。dict按key查找,所以一个dict中key不能重复。
(2)存储的key-value对象没有顺序,当print d时打印顺序不一定是创建顺序,dict内部是无序的,不能用dict存储有序集合。
(3)作为key的元素必须不可变。Python的基本类型如字符串、整数、浮点数都是不可变的,都可以作为key,但是list是可变的,不能作为key。
更新dict
可以在dict中增添新的元素:
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
>>> d['Paul'] = 72
如果key已经存在则赋值会用新value替换原来的value。
使用for循环遍历dict:
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
for key in d:
print key+':',d[key]
结果:
Lisa: 85
Adam: 95
Bart: 59
set类型
1.set持有一系列元素,和list很像;set的元素没有重复而且是无序的,和dict的key很像
2.创建set:
>>> s = set(['A','B','C'])
>>> print s
set(['A','C','B'])
注意:set内部存储元素是无序的(list是有序的),所以上述打印顺序与创建顺序不同
3.set不能包含重复的元素,当传入重复元素时,会自动去掉重复元素
>>> s = set(['A', 'B', 'C', 'C'])
>>> print s
set(['A', 'C', 'B'])
>>> len(s)
3
set存储的是无序集合,因此访问set中某个元素就是判断一个元素是否在set中
>>> s = set(['Adam', 'Lisa', 'Bart', 'Paul'])
>>> 'Bart' in s
True
>>> 'bart' in s
False
大小写很重要,’Bart’和’bart’被认为是两个不同的元素
set的特点:
(1)set的内部结构和dict很像,唯一区别是不存储value,因此,判断一个元素是否在set中速度很快。
(2)set存储的元素和dict的key类似,必须是不变对象,因此,任何可变对象是不能放入set中的。
(3)set存储的元素也是没有顺序的。
set也是一个集合,因此可以用for循环来遍历:
>>> s = set(['Adam', 'Lisa', 'Bart'])
>>> for name in s:
print name
...
Lisa
Adam
Bart
注意:for循环在遍历set时,元素顺序和list顺序可能不同。
1.新元素添加到set中:set的add()方法
>>> s = set([1, 2, 3])
>>> s.add(4)
>>> print s
set([1, 2, 3, 4])
如果要添加的元素已经在set中了,add()不会报错,也不会把该元素再添加进去了
2.删除set中的元素:用set的remove()方法
>>> s = set([1, 2, 3, 4])
>>> s.remove(4)
>>> print s
set([1, 2, 3])
如果删除的元素不在set中则会报错。
所以用add()可以直接添加,而remove()前需要判断。
函数
Python的内置函数可以在https://docs.python.org/2/library/functions.html上查看到
abs():求绝对值
cmp(x,y):比较x和y的大小
int():把其他类型转换为整型
>>> int('123')
123
>>> int(12.34)
12
str():把其他类型转换为字符串
>>> str(123)
'123'
>>> str(1.23)
'1.23'
函数的定义
def my_abs(x):
if x >= 0:
return x
else:
return -x
如果没有return语句则返回None,return None简写为return
函数可以返回多值,此时的返回值是一个tuple,多个变量可以同时接受一个tuple,按位置赋给对应的值。
import math
def move(x, y, step, angle):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
>>> x, y = move(100, 100, 60, math.pi / 6)
>>> print x, y
151.961524227 70.0
>>> r = move(100, 100, 60, math.pi / 6)
>>> print r
(151.96152422706632, 70.0)
注意:import math之后,在调用math中的函数时,要写成”math.函数名”的形式。
递归函数:考虑两种情况,第一种就是特殊情况即n=1时,第二种是通常情况n>1时分成两种考虑,一个是n-1一个是1。
两个例子:
求阶乘:
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
汉诺塔:
# -*- coding: UTF-8 -*-
def move(n, a, b, c):
if n == 1:
print a,'-->',c
else:
move(n-1,a,c,b)
print a,'-->',c
move(n-1,b,a,c)
缺省参数:默认参数只能定义在必需参数的后面
计算x的n次方:
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
>>> power(5)
25
可变参数:让一个函数能接受任意个参数,会把传入的一组参数组装成一个tuple传递给可变参数,所以直接把变量args看成一个tuple即可,用len(args)可以计算tuple中的元素个数。
def fn(*args):
print args
>>> fn()
()
>>> fn('a')
('a',)
>>> fn('a', 'b')
('a', 'b')
>>> fn('a', 'b', 'c')
('a', 'b', 'c')
切片
对list和tuple切片,最后得到的还是list和tuple
>>> L = ['Adam', 'Lisa', 'Bart', 'Paul']
>>> L[1:3] #从索引1开始到索引3,但不包括索引3
['Lisa', 'Bart']
>>> L[0:3] #从索引0开始到索引3,不包括索引3
['Adam', 'Lisa', 'Bart']
>>> L[:3] #从索引0开始,0可以省略
['Adam', 'Lisa', 'Bart']
>>> L[:] #从头到尾,实际上是复制出了一个新list
['Adam', 'Lisa', 'Bart', 'Paul']
>>> L[::2] #从头到尾,每两个元素取一个,每隔一个元素取一个
['Adam', 'Bart']
倒序切片:
最后一个元素索引为-1,其他切片规则与正序相同
仍然是包含起始索引,不包含结束索引。
截取字符串直接用切片操作完成:
>>> 'ABCDEFG'[:3]
'ABC'
>>> 'ABCDEFG'[-3:]
'EFG'
>>> 'ABCDEFG'[::2]
'ACEG'
迭代
给定一个list或者tuple,用”for in”循环来遍历这个list或者tuple,这种遍历称为迭代。
Python的for循环不仅可以用在list或者tuple上,还可以用在其他任何迭代对象上。迭代操作就是对于一个集合,无论该集合有序还是无序,用for循环可以依次取出集合的每一个元素。
注意: 集合是指包含一组元素的数据结构,我们已经介绍的包括:
1. 有序集合:list,tuple,str和unicode;
2. 无序集合:set
3. 无序集合并且具有 key-value 对:dict
Python中的迭代永远是取出元素本身,而非元素的索引。
为了取出元素索引和元素本身,使用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
或者
for index, name in enumerate(L):
print index, '-', name
函数zip()可以把两个list变成一个list:
>>> zip([10, 20, 30], ['A', 'B', 'C'])
[(10, 'A'), (20, 'B'), (30, 'C')]
函数range(1,101)表示从1到100的数列,包括1不包括101。
for循环迭代dict可以每次拿到dict的一个key,要想迭代到dict的value,有两种方法:
(1)dict的value()方法
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.values()
# [85, 95, 59]
for v in d.values():
print v
# 85
# 95
# 59
(2)dict的itervalues()方法
d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
print d.itervalues()
# <dictionary-valueiterator object at 0x106adbb50>
for v in d.itervalues():
print v
# 85
# 95
# 59
两个方法的不同之处:
1. values() 方法实际上把一个 dict 转换成了包含 value 的list。
2. 但是 itervalues() 方法不会转换,它会在迭代过程中依次从 dict 中取出 value,所以 itervalues() 方法比 values() 方法节省了生成 list 所需的内存。
如果一个对象说自己可迭代,那我们就直接用 for 循环去迭代它,可见,迭代是一种抽象的数据操作,它不对迭代对象内部的数据有任何要求。
在for循环中同时迭代dict的key和value:
(1)items()方法
>>> d = { 'Adam': 95, 'Lisa': 85, 'Bart': 59 }
>>> print d.items()
[('Lisa', 85), ('Adam', 95), ('Bart', 59)]
items() 方法把dict对象转换成了包含tuple的list
(2)iteritems()方法
不把dict转换成list,而是在迭代过程中不断给出tuple,所以不占用额外内存
列表生成式
用range(1,11)可以生成list[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
用range(1, 100, 2) 可以生成list [1, 3, 5, 7, 9,…]
列表生成式:
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
1.字符串可以通过%进行格式化:
name = 'lnq'
print '%s' % name
输出:lnq
2.字符串的join()方法可以把一个list拼接成一个字符串:
d = ['lnq','is','cute']
print join(d) #语法错误
print ''.join(d)
#输出:lnqiscute
print ' '.join(d)
#输出:lnq is cute
print '\n'.join(d)
#输出:
lnq
is
cute
条件过滤表达式:
只想要偶数的平方
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
有了if条件,只有当if判断为True的时候,才把循环的当前元素添加到列表中
isinstance(x,str)可以判断变量x是否是字符串,若是则返回True
字符串的upper()方法可以返回大写字母字符串
>>> print lnq.upper()
LNQ
多层表达式:
对于字符串 ‘ABC’ 和 ‘123’,可以使用两层循环,生成全排列:
>>> [m + n for m in 'ABC' for n in '123']
['A1', 'A2', 'A3', 'B1', 'B2', 'B3', 'C1', 'C2', 'C3']
这里有一个关于变量类型的注意点:
print [m+n for m in '123' for n in '123']
print [m*10+n for m in range(1,4) for n in range(1,4)]
输出:
['11', '12', '13', '21', '22', '23', '31', '32', '33']
[11, 12, 13, 21, 22, 23, 31, 32, 33]
这两个list一个元素是字符串型,一个是整型。