数据类型和变量

数据类型

Python基本的数据类型有:整数、浮点数、字符串、布尔值、空值。

  • Python的整数没有大小限制

  • 浮点数(也就是小数,之所以称为浮点数,是因为按照科学计数法表示时,一个浮点数的小数点位置是可变的),浮点数也没有大小限制,但是超出一定范围会直接表示为inf(无限大)

  • Python中整数运算永远是精确的,而浮点数运算则会有四舍五入的误差。

  • Python中的两种除法:

    • /:计算结果是浮点数。即使是两个整数进行运算,结果仍然是浮点数。
    • 10 / 3将返回3.3333333333333335;而9 / 3将返回3.0
    • //:地板除,只保留除法运算结果的整数部分,不进行四舍五入。
    • 10 // 3将返回3
    • %:余数运算,可以得到两个整数相除的余数
    • 10 % 3将返回1
  • 字符串是用单引号'或双引号"括起来的任意文本,比如'abc''123'等。

    • 如果字符串内部既包含'又包含",可以用转义字符\来标识,比如:'I\'m \"OK\"!'表示的字符是:I'm "OK"!'

    • \n表示换行,\t表示制表符,如果要显示字符\本身,要进行转义,即\\表示的字符就是\

    • r'...'表示引号内部的字符串全部不转义:

      1
      
      print(r'\\\t\\')  #用了r''之后,''中的内容将原样输出,不会进行转义
    • '''...'''的格式可以直接用回车代替\n显示多行内容:

      1
      2
      3
      
      print('''第一行
      第二行
      第三行''') 
  • 布尔值:即TrueFalse(T和F要大写),布尔值可以用andornot进行运算。

  • 空值:Python中的空值用None表示。None不能理解为0,因为0是有意义的,而None是一个特殊的空值。

变量和常量

  • Python中,等号=是赋值语句,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,可以是不同数据类型的变量。
  • 当我们写a = 'ABC'时,Python解释器干了两件事:
    • 在内存中创建了一个名为'ABC'的字符串
    • 在内存中创建了一个名为'a'的变量,并把他指向'ABC'
  • 当我们将变量a赋值给另一个变量b时,实际上是把变量b指向变量a所指向的数据。

    1
    2
    3
    4
    
    a = 'ABC'
    b = a
    a = 'XYZ'
    print(b)   #最终将显示ABC
  • 常量就是不能变的变量,通常用全部大写的变量名表示常量:PI = 3.14159265359,但事实上PI仍然是一个变量,Python根本没有任何机制保证PI不会被改变。用全部大写的变量名表示常量只是一个约定俗成的用法。

字符串和编码

字符编码

Unicode把所有国家的语言都统一到了一套编码里。为了避免(大量使用英文时的)浪费,出现了“可变长编码”UTF-8编码。

Python的字符串

在Python 3版本中,字符串默认以Unicode编码,所以Python的字符串支持多种语言。

  • ord()函数:以一个字符(长度为1的字符串)作为参数,返回对应的 ASCII 数值,或者 Unicode 数值。
  • chr()函数:用一个范围在 range(256)内的(就是0~255)整数作参数,返回值是当前整数对应的 ASCII 字符。

    1
    2
    3
    4
    
    ord('A')    #将返回65
    ord('中')   #将返回20013
    chr(66)     #将返回'B'
    chr(97)		#将返回'a'
  • len()函数:返回对象(字符、列表、元组等)长度或项目个数。

    1
    2
    3
    4
    5
    6
    7
    8
    
    >>>len('ABC')
    3
    >>>len('中文')
    2
    >>>len('ABC'.encode('UTF-8'))
    3
    >>> len('中文'.encode('utf-8'))
    6

1个中文字符经过UTF-8编码后通常会占用3个字节,而1个英文字符只占用1个字节。

格式化字符串

在Python中,采用的格式化方式和C语言是一致的,用%实现,举例如下:

1
2
3
4
print('Hello, %s' % 'world')
#显示'Hello, world'
print('Hi, %s, you have $%d.' % ('Michael', 1000000))
#显示'Hi, Michael, you have $1000000.'

在字符串内部,%s表示用字符串替换,%d表示用整数替换,有几个%?占位符,后面就跟几个变量或者值,顺序要对应好。如果只有一个%?,括号可以省略。

常见的占位符有:

占位符 替换内容
%d 整数
%f 浮点数
%s 字符串
%x 十六进制整数

格式化操作符辅助指令:

符号 功能
* 定义宽度或者小数点精度
- 用做左对齐
0 显示的数字不足规定位数则在前面用’0’填充,而不是默认的空格
m.n. m 是显示的最小总宽度,n 是小数点后的位数(如果可用的话)

例:

1
2
print('%3d--%02d' % (3, 1))    #将显示__2--01(__表示空格)
print("%.2f" % 3.1415926)      #将显示3.14

%%来表示一个%

1
print('growth rate: %d %%' % 7)    #将返回'growth rate: 7 %''

format()

str.format,增强了字符串格式化的功能。基本语法是通过 {}: 来代替以前的 %

format 函数可以接受不限个参数,位置可以不按顺序。

1
2
3
4
5
6
>>>"{} {}".format("hello", "world")    # 不设置指定位置,按默认顺序
'hello world'
>>> "{0} {1}".format("hello", "world")  # 设置指定位置
'hello world'
>>> "{1} {0} {1}".format("hello", "world")  # 设置指定位置
'world hello world'

也可以设置参数:

1
2
3
4
5
6
7
8
9
print("姓名:{name}, 分数 {score}".format(name="王小明", score="98"))
 
# 通过字典设置参数
site = {"name": "王小明", "score": "98"}
print("姓名:{name}, 分数 {score}".format(**site))
 
# 通过列表索引设置参数
my_list = ['王小明', '98']
print("姓名:{0[0]}, 分数 {0[1]}".format(my_list))  # "0" 是必须的

输出结果为:

1
2
3
姓名:王小明, 分数 98
姓名:王小明, 分数 98
姓名:王小明, 分数 98

实际应用:

1
2
3
4
name = input('请输入学生姓名:')
s1 = float(input('请输入去年的成绩:'))
s2 = float(input('请输入今年的成绩:'))
print('%s的成绩从去年的%.2f变成了今年的%.2f,提升了%.2f%%' % (name, s1, s2, (s2 - s1) / s1 * 100))

结果为(.2f的格式会进行四舍五入):

1
2
3
4
请输入学生姓名:小明
请输入去年的成绩:60.5
请输入今年的成绩:90
小明的成绩从去年的60.50变成了今年的90.00,提升了48.76%

Python序列

序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字 - 它的位置/索引,第一个索引是0,第二个索引是1,依此类推。

Python有6个序列的内置类型,最常见的是列表和元组。

序列都可以进行的操作包括索引,切片,加,乘,检查成员。

Python内置确定序列的长度(len()以及确定最大max()和最小min()的元素的方法。

list列表

创建列表

列表名 = [xxx, xxx, xxx]来创建。列表中的数据项不需要具有相同的类型。如下:

1
2
3
classmates = ['张三', '李四', '王五']
print(classmates)     #将返回['张三', '李四', '王五']
list = ['physics', 'chemistry', 1997, 2000]

list元素可以是另一个list,比如:

1
2
3
s = ['Python', 'Java', ['a', 'b'], 'C']
print(s)			#将返回['Python', 'Java', ['a', 'b'], 'C']
print(len(s))		#将返回4

要注意s只有4个元素,其中s[2]又是一个list:

1
2
p = ['a', 'b']
s = ['Python', 'Java', p, 'C']

要拿到'b'可以写p[1]或者s[2][1],因此s可以看成是一个二维数组,类似的还有三维、四维……数组,不过很少用到。

访问列表

使用下标索引(索引是从0开始的)来访问列表中的值,也可以使用方括号的形式截取字符,如下所示:

1
2
3
4
print(classmates[0])    #返回张三
print(classmates[1])	#返回李四
list = [1, 2, 3, 4, 5, 6, 7]
print(list[1:5])		#返回[2, 3, 4, 5]

可以用-1做索引,直接获取最后一个元素,以此类推,可以获取倒数第2个、倒数第3个:

1
2
3
print(classmates[-1])	#返回王五
print(classmates[-2]) 	#返回李四
print(classmates[-3])	#返回张三

更新列表

可以对列表的数据项进行修改或更新,使用append()方法来添加列表项,如下所示:

1
2
classmates.append('赵六')
print(classmates)	#将返回['张三', '李四', '王五', '赵六']

也可以把元素插入到指定的位置,比如索引号为1的位置:

1
2
classmates.insert(1, '田七')
print(classmates)	#将返回['张三', '田七', '李四', '王五', '赵六']

要把某个元素替换成别的元素,可以直接赋值给对应的索引位置:

1
2
classmates[1] = '二蛋'
print(classmates)	#将返回['张三', '二蛋', '王五']

删除列表元素

使用 del 语句来删除列表的元素,如下实例:

1
2
3
list1 = ['physics', 'chemistry', 1997, 2000]
del list1[2]
print list1			#将返回['physics', 'chemistry', 2000]

pop()方法删除list末尾的元素:

1
2
classmates.pop()
print(classmates)	#将返回['张三', '田七', '李四', '王五']

pop(i)方法(其中i是索引位置)删除指定位置的元素:

1
2
classmates.pop(1)
print(classmates)	#将返回['张三', '李四', '王五']

列表截取

Python 的列表截取实例如下:

1
2
3
4
L = ['Google', 'Runoob', 'Taobao']
print(L[2])			#读取列表中第三个元素,返回'Taobao'
print(L[-2])		#读取列表中倒数第二个元素,返回'Runoob'
print(L[1:])		#从第二个元素开始截取列表,返回['Runoob', 'Taobao']

列表函数&方法

函数:

函数 作用
len(list) 返回列表元素个数
max(list) 返回列表元素最大值
min(list) 返回列表元素最小值
list(seq) 将元组转换为列表

方法:

方法 作用
list.append(obj) 在列表末尾添加新的对象
list.count(obj) 统计某个元素在列表中出现的次数
list.extend(seq) 在列表末尾一次性追加另一个序列中的多个值
list.index(obj) 从列表中找出某个值第一个匹配项的索引位置
list.insert(index, obj) 将对象插入列表
list.pop([index=-1]) 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
list.remove(obj) 移除列表中某个值的第一个匹配项
list.reverse() 反向列表中元素
list.sort() 对原列表进行排序

tuple元组

元组与列表类似,不同之处在于元组的元素不能修改。元组使用小括号,列表使用方括号。

创建元组

元组名= (xxx, ,xxx, xxx)即可,如下实例:

1
2
3
tup1 = ('physics', 'chemistry', 1997, 2000) 
tup2 = (1, 2, 3, 4, 5 ) 
tup3 = "a", "b", "c", "d"

创建空元组tup1 = ()

元组中只包含一个元素时,需要在元素后面添加逗号tup1 = (50,)

访问元组

使用下标索引来访问元组中的值,如下实例:

1
2
3
4
5
tup1 = ('physics', 'chemistry', 1997, 2000)
tup2 = (1, 2, 3, 4, 5, 6, 7 )
 
print (tup1[0]) 		#返回'physics'
print (tup2[1:5])		#返回(2, 3, 4, 5)

修改元组

元组中的元素值不允许修改,但可以对元组进行连接组合,如下实例:

1
2
3
4
5
6
7
8
9
tup1 = (12, 34.56)
tup2 = ('abc', 'xyz')
 
# 以下修改元组元素操作是非法的。
# tup1[0] = 100
 
# 创建一个新的元组
tup3 = tup1 + tup2
print tup3			#返回(12, 34.56, 'abc', 'xyz')

删除元组

元组中的元素值不允许删除,但可以使用del语句来删除整个元组,如下实例:

1
2
3
4
tup = ('physics', 'chemistry', 1997, 2000)

del tup
print tup		#元组被删除后,输出变量会返回错误信息(元组未定义)

元组运算符

元组之间可以使用 + 号和 * 号进行运算。运算后会生成一个新的元组。

Python 表达式 结果 描述
len((1, 2, 3)) 3 计算元素个数
(1, 2, 3) + (4, 5, 6) (1, 2, 3, 4, 5, 6) 连接
(‘Hi!’,) * 4 (‘Hi!’, ‘Hi!’, ‘Hi!’, ‘Hi!’) 复制
3 in (1, 2, 3) True 元素是否存在
for x in (1, 2, 3): print x, 1 2 3 迭代

元组索引,截取

可以访问元组中的指定位置的元素,也可以截取索引中的一段元素,如下所示:

1
L = ('spam', 'Spam', 'SPAM!')
Python 表达式 结果 描述
L[2] ‘SPAM!’ 读取第三个元素
L[-2] ‘Spam’ 反向读取,读取倒数第二个元素
L[1:] (‘Spam’, ‘SPAM!’) 截取元素

元组内置函数与列表类似(len(), max(), min(), tuple())

dict 字典

字典(在其他语言中也称为map)是另一种可变容器模型,且可存储任意类型对象。使用键-值(key-value)存储,具有极快的查找速度。

字典的每个键值key => value对用冒号 : 分割,每个键值对之间用逗号 , 分割,整个字典包括在花括号 {} 中 ,格式如下所示:

1
d = {key1 : value1, key2 : value2 }

键一般是唯一的,如果重复最后的一个键值对会替换前面的,值不需要唯一。

1
2
3
dict1 = {'a': 1, 'b': 2, 'b': '3'}
print(dict1['b'])		#返回'3'
print(dict1)				#返回{'a': 1, 'b': '3'}

创建字典

字典的值可以取任何数据类型,但键必须是不可变的,如字符串,数字或元组。

1
2
3
dict1 = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'}
dict2 = { 'abc': 456 }
dict3 = { 'abc': 123, 98.6: 37 }

访问字典里的值

1
2
3
4
dict1 = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
 
print (dict1['Name'])		#返回Zara
print (dict1['Age'])		#返回7

修改字典

1
2
3
4
5
6
7
dict1 = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
 
dict1['Age'] = 8 # 更新
dict1['School'] = "RUNOOB" # 添加
 
print (dict1['Age'])		#返回8
print (dict1['School'])		#返回RUNOOB

删除字典元素

删除一个字典用del命令(可以删除字典里单一的元素也可以清空字典),如下实例:

1
2
3
4
5
6
7
dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}
del dict['Name']  		# 删除键是'Name'的条目
dict.clear()      		# 清空字典所有条目
del dict          		# 删除字典
 
print "dict['Age']: ", dict['Age'] 				#会报错因为用del后字典不再存在
print "dict['School']: ", dict['School']		#会报错因为用del后字典不再存在

字典键的特性

  1. 不允许同一个键出现两次。创建时如果同一个键被赋值两次,后一个值会被记住
  2. 键必须不可变,可以用数字,字符串或元组充当,但是不能用列表
  3. dict内部存放的顺序和key放入的顺序是没有关系的

和list比较,dict有以下几个特点:

  1. 查找和插入的速度极快,不会随着key的增加而变慢;
  2. 需要占用大量的内存,内存浪费多。
  3. dict是用空间来换取时间的一种方法。

set集合

set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。

要创建一个set,需要提供一个list作为输入集合:

1
2
s = set([1, 2, 3])
print (s)	#返回{1, 2, 3}

重复元素在set中自动被过滤:

1
2
s = set([1, 2, 2, 3, 3, 3])
print(s)	#返回{1, 2, 3}

通过add(key)方法添加元素到set中:

1
2
3
4
s.add(4)
print(s)	#显示{1, 2, 3, 4}
s.add(s)
print(s)	#显示{1, 2, 3, 4}

通过remove(key)方法删除元素:

1
2
s.remove(4)
print(s)	#显示{1, 2, 3}

set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:

1
2
3
4
s1 = set([1, 2, 3])
s2 = set([2, 3, 4])
print(s1 & s2)	#显示{2, 3}
print(s1 | s2)	#显示{1, 2, 3, 4}

set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。

条件判断

if语句实现条件判断。根据Python的缩进规则,如果if语句判断是True,就把缩进的n行语句执行了,否则,什么也不做。

可以给if添加一个else语句,意思是,如果if判断是False,不要执行if的内容,去把else执行了。

注意不要少写了冒号:!!!!

1
2
3
4
5
6
7
age = 16	#将执行else语句中的两行print语句
if age >= 18:
    print('你今年%d岁' % age)
    print('恭喜,你已经成年了')
else:
    print('你今年%d岁' % age)
    print('恭喜,你正值青春年华')

当然上面的判断完全可以用elif做更细致的判断:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
age = 16
if age >= 18:
    print('你今年%d岁' % age)
    print('恭喜,你已经成年了')
elif age >= 6:
    print('你今年%d岁' % age)
    print('恭喜,你正值青春年华')
else:
    print('你今年%d岁' % age)
    print('恭喜,你处在最无忧无虑的年龄')    

elifelse if的缩写,可以有多个elif,所以if语句的完整形式就是:

1
2
3
4
5
6
7
8
if <条件判断1>:
    <执行1>
elif <条件判断2>:
    <执行2>
elif <条件判断3>:
    <执行3>
else:
    <执行4>

if判断条件还可以简写,比如写:

1
2
if x:
    print('True')

只要x是非零数值、非空字符串、非空list等,就判断为True,否则为False

循环

for…in循环

依次把list或tuple中的每个元素迭代出来:

1
2
3
names = ['Michael', 'Bob', 'Tracy']
for name in names:
    print(name)

执行这段代码,会依次打印names的每一个元素:

1
2
3
Michael
Bob
Tracy

再比如计算1-10的整数之和,可以用一个sum变量做累加:

1
2
3
4
s = 0
for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
    s = s + x
print(s)

如果要计算1-100的整数之和,从1写到100有点困难,Python提供一个range()函数,可以生成一个整数序列,再通过list()函数可以转换为list。比如range(5)生成的序列是从0开始小于5的整数:

1
print(list(range(5)))	#返回[0, 1, 2, 3, 4]

range(101)可以生成0-100的整数序列,计算如下:

1
2
3
4
s = 0
for x in range(101):
    s = s + x
print(s)

while循环

只要条件满足,就不断循环,条件不满足时退出循环。

比如计算100以内所有奇数之和,可以用while循环实现:

1
2
3
4
5
6
s = 0
n = 99
while n > 0:
    s = s + n
    n = n - 2
print(s)

在循环内部变量n不断自减,直到变为-1时,不再满足while条件,循环退出。

1
2
3
4
L = ['Bart', 'Lisa', 'Adam']
n = len(L)
for name in L:
    print('Hello, %s!' % name)

上面的程序结果为:

1
2
3
Hello, Bart!
Hello, Lisa!
Hello, Adam!

break

在循环中,break语句可以提前退出循环。例如,本来要循环打印1~100的数字:

1
2
3
4
5
n = 1
while n <= 100:
    print(n)
    n = n + 1
print('END')

上面的代码可以打印出1~100。

如果要提前结束循环,可以用break语句:

1
2
3
4
5
6
7
n = 1
while n <= 100:
    if n > 10:		# 当n = 11时,条件满足,执行break语句
        break		# break语句会结束当前循环
    print(n)
    n = n + 1
print('END')

执行上面的代码可以看到,打印出1~10后,紧接着打印END,程序结束。

可见break的作用是提前结束循环。

continue

在循环过程中,也可以通过continue语句,跳过当前的这次循环,直接开始下一次循环。

1
2
3
4
n = 0
while n < 10:
    n = n + 1
    print(n)

上面的程序可以打印出1~10。但是,如果只打印奇数,可以用continue语句跳过某些循环:

1
2
3
4
5
6
n = 0
while n < 10:
    n = n + 1
    if n % 2 == 0: # 如果n是偶数,执行continue语句
        continue # continue语句会直接继续下一轮循环,后续的print()语句不会执行
    print(n)

执行上面的代码可以看到,打印的不再是1~10,而是1,3,5,7,9。

可见continue的作用是提前结束本轮循环,并直接开始下一轮循环。

小结

循环是让计算机做重复任务的有效的方法。

break语句可以在循环过程中直接退出循环,而continue语句可以提前结束本轮循环,并直接开始下一轮循环。这两个语句通常都*必须*配合if语句使用。

不要滥用breakcontinue语句。breakcontinue会造成代码执行逻辑分叉过多,容易出错。

有些时候,如果代码写得有问题,会让程序陷入“死循环”。这时可以用Ctrl+C退出程序,或者强制结束Python进程。