前言
知识点总结于《Python编程从入门到实践》 Eric Matthes 著 袁国忠 译
变量和简单数据类型
变量
命名与使用
变量名只能包含数字、字母以及下划线。可以以字母或下划线开头,不可以数字开头。
不可用函数名或关键字。
慎用小写字母“l”和大写字母“O”,容易错看为数字1和0。
尽量避免使用大写字母。
字符串
定义
字符串就是一系列字符,用引号括起的都是字符串,可以是单引号''
,也可是双引号""
。
修改字符串大小写的方法
title()
功能:将字符串中的每个单词的首字母变为大写。
例:
name = 'steve jobs'
print(name.title())
输出:
Steve Jobs
upper()和lower()
功能:将字符串改为全部大或者小写。
例:
name = 'Steve Jobs'
print(name.upper())
print(name.lower())
输出:
STEVE JOBS
steve jobs
合并(拼接)字符串
Python用+
号来合并字符串。
这种方法称为拼接。
例:
first_name = 'Steve'
last_name = 'Jobs'
name = first_name + ' ' +last_name
print(name)
输出:
Steve Jobs
删除空白
rstrip()
功能:消除字符串左边的空白。
lstrip()
功能:消除字符串右边的空白。
strip()
功能:消除字符串两边的空白。
总例
name = ' python '
print("\'" + name.lstrip() + "\'")
print("\'" + name.rstrip() + "\'")
print("\'" + name.strip() + "\'")
输出:
'python '
' python'
'python'
数字
浮点数
浮点数运算结果包含的小数位数是不确定的。
例:
print(0.1 + 0.2)
print(0.3 * 2)
输出:
0.30000000000000004
0.6
str()
功能:将 非字符串值 表示为 字符串值。
例:
age = 18
message = "Happy " + age + "rd" + " birthday!"
print(message)
直接使用age
会报错。
TypeError: Can't convert 'int' object to str implicitly
修改代码,使用str():
age = 18
message = "Happy " + str(age) + "rd" + " birthday!"
print(message)
输出:
Happy 18rd birthday!
注释
用#
开头表示注释。
列表简介
定义
列表由一些列按特定顺序排列的元素组成,用[]
来表示列表。
命名上,建议使用复数名称。
类似其他语言的“数组”。
bicycles = ['trek','readline','cannondale']
访问列表元素
与数组相同,通过下标取得对应位置的元素。
特殊地,Python中为访问最后一个列表元素提供特殊方法。通过将索引指定为 -1
,可直接取道最后一个元素。
同理-2
,-3
便是倒数第二第三个元素。
添加元素
append()
在列表末尾添加一个元素。
例:
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(fruits)
fruits.append('mango')
print(fruits)
输出:
['lemon', 'apple', 'banana', 'peach', 'strawberry']
['lemon', 'apple', 'banana', 'peach', 'strawberry', 'mango']
insert()
可在列表任何位置插入新元素。
此方法有两个参数,索引值与新元素的值。
例:
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(fruits)
fruits.insert(2, 'mango')
print(fruits)
输出:
['lemon', 'apple', 'banana', 'peach', 'strawberry']
['lemon', 'apple', 'mango', 'banana', 'peach', 'strawberry']
删除元素
del 语句
如果知道要删除的元素在列表中的位置,可以使用del
语句。
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(fruits)
del fruits[0]
print(fruits)
输出:
['lemon', 'apple', 'banana', 'peach', 'strawberry']
['apple', 'banana', 'peach', 'strawberry']
pop()
弹出指定位置的元素,无参方法为弹出最后一个元素。
弹出后的值可以继续使用。
例:
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(fruits)
favorite = fruits.pop(-2)
print(favorite.title() + " is my favorite fruit.")
输出:
Peach is my favorite fruit.
remove()
有时我们不知道要删除的元素的位置,但知道值,可以根据值来删除元素。
同pop()
,删除后也可以使用删除后的值。
例:
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(fruits)
favorite = fruits.remove('peach')
print(favorite.title() + " is my favorite fruit.")
Peach is my favorite fruit.
注意:remove()
只删除第一个指定的值。如果要删除的值可能在列表中出现多次,需要使用循环判断。
组织列表
sort()
对列表进行永久性排序。
例:
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(fruits)
fruits.sort()
print(fruits)
输出:
['lemon', 'apple', 'banana', 'peach', 'strawberry']
['apple', 'banana', 'lemon', 'peach', 'strawberry']
结果按字母顺序排列,即按ASCII码由小到大排序。
若要逆序排序:只需向sort()
传递参数reverse=True
。
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(fruits)
fruits.sort(reverse=True)
print(fruits)
输出:
['lemon', 'apple', 'banana', 'peach', 'strawberry']
['strawberry', 'peach', 'lemon', 'banana', 'apple']
sorted()
对列表进行临时排序,不改变列表本身。
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(sorted(fruits))
print(fruits)
输出:
['apple', 'banana', 'lemon', 'peach', 'strawberry']
['lemon', 'apple', 'banana', 'peach', 'strawberry']
reverse()
反转列表的顺序,不是按字母顺序。
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(fruits)
fruits.reverse()
print(fruits)
输出:
['lemon', 'apple', 'banana', 'peach', 'strawberry']
['strawberry', 'peach', 'banana', 'apple', 'lemon']
len()
获得列表的长度,即列表元素的个数。
例:
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(len(fruits))
输出:
5
操作列表
for循环
例:
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
for fruit in fruits:
print(fruit)
输出:
lemon
apple
banana
peach
strawberry
Python首先读取第一行代码:
for fruit in fruits:
获取fruits
的第一个值'lemon'
,并将其存储到变量fruit
中。接下来,读取下一行代码。
print(fruit)
打印值。因为列表中还有元素,回到第一行代码然后获取下一个元素,再打印,直到打印完所有元素。
注意:别忘记冒号。
创建数值列表
range()
生成一系列数字。
例:
for value in range(1,5):
print(value)
输出:
1
2
3
4
观察到,只到数字5就停下了。
range()
函数让Python从你指定的第一个数字开始数,并在到达你指定的第二个值后停止,因此输出不会包含第二个值。
list()
要创建数字列表,可以使用函数list()
将range()
的结果直接转换为列表。
如果将range()
作为list()
的参数,输出将为一个数字列表。
例:
numbers = list(range(1,5))
print(numbers)
输出:
[1, 2, 3, 4]
range()
函数还可以指定步长,例如打印从1~10的奇数:
numbers = list(range(1,10,2))
print(numbers)
输出:
[1, 3, 5, 7, 9]
range()
从1开始数,然后不断加2,直到到达终值。
对数字列表执行简单的统计计算
找到数字列表的最大值、最小值或综合。
numbers = list(range(1,10,2))
print(max(numbers))
print(min(numbers))
print(sum(numbers))
输出:
9
1
25
列表解析
列表解析将for
循环和创建新元素的代码合并成一行,并自动附加新元素。
如,传建一个从1~10的平方数的列表(在Python中,两个星号**
表示乘方):
numbers = [value**2 for value in range(1,11)]
print(numbers)
输出:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
这个功能真的超帅的!
主要有两个部分,一是左边的表达式,这里是value**2
,然后是左边的 for value in range(1,11)
用于给表达式提供值。
使用列表的一部分
切片
要创建切片,可指定要使用的一个元素和最后一个元素的索引。与函数rang()
一样,Python在到达你指定的第二个索引的前一个元素后停止。
例:
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(fruits[0:2])
输出:
['lemon', 'apple']
看清楚,两个索引之间用的是冒号:
。
若没有制定一个索引,将自动从列表开头开始:
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(fruits[:2])
输出:
['lemon', 'apple']
若没有指定第二个索引,将自动从第一个索引处开始终止于末尾处:
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(fruits[1:])
输出:
['apple', 'banana', 'peach', 'strawberry']
小技巧,使用负号索引打印最后三个元素:
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(fruits[-3:])
输出:
['banana', 'peach', 'strawberry']
复制列表
my_fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
friend_fruits = my_fruits[:]
print(my_fruits)
print(friend_fruits)
输出:
['lemon', 'apple', 'banana', 'peach', 'strawberry']
['lemon', 'apple', 'banana', 'peach', 'strawberry']
我们为什么不用=
号直接赋值呢?
就像Java的引用类型一样,只是让两个变量指向了同一个列表而已,变来变去还是只有一个列表,所以要用切片。
元组
Python将不能修改的元素称为不可变的,不可变的列表称为元组。
定义元组
元租用圆括号()
来标识,内容不能修改。
例:
my_fruits = ('lemon', 'apple', 'banana', 'peach', 'strawberry')
这就是我的水果,谁都不能抢不能变。
遍历与获取其中元素的方法类比列表。
修改元组变量
就像是Java的字符串常量一样,一个字符串变量可以指向不同的字符串常量。
my_fruits = ('lemon', 'apple', 'banana', 'peach', 'strawberry')
print(my_fruits)
my_fruits = ('mango', 'pineapple', 'pear', 'watermelon', 'orange')
print(my_fruits)
输出:
('lemon', 'apple', 'banana', 'peach', 'strawberry')
('mango', 'pineapple', 'pear', 'watermelon', 'orange')
if 语句
检查是否相等
Python中的==
是按值比较,不是Java中的看引用对象是否相同。
例:
my_fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
friend_fruits = my_fruits
print(friend_fruits==my_fruits)
friend_fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
print(friend_fruits==my_fruits)
输出:
True
True
检查多个条件
Python中用and
和or
来表示与和或。
检查特定值是否(不)包含在列表中
用in
和not in
。
例:
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
if 'peach' in fruits:
print('Yes, you know my heart. I love peach.')
输出:
Yes, you know my heart. I love peach.
if 语句
if-elif-else
就注意一下这个与其他语言的区别就好了。
字典
定义
类似于Java的Map或PHP的键-值对数组。
在Python中,字典是一系列键-值对。
键是唯一的,值可重复。
字典放在花括号{}
中。
空字典:
student = {}
访问字典中的值
只需指定对应值的键:
student = {'name': 'wang', 'age': 18}
print(student['name'])
输出:
wang
添加键-值对
和列表不同,不需要专门调用append()
或insert()
这类方法。
字典是一种动态结构,可对视在其中添加键-值对。
要添加键-值对,可依次指定字典名,用方括号括起来的键和相关联的值:
student = {'name': 'wang', 'age': 18}
print(student)
student['home'] = 'Shanxi'
print(student)
输出:
{'age': 18, 'name': 'wang'}
{'age': 18, 'home': 'Shanxi', 'name': 'wang'}
注意:键-值对的排列顺序与添加顺序无关。Python不关心键-值对的添加顺序,只关心键和值的关联关系,如上例,home
被加到了中间,多运行几次,它可能出现在任何一个位置。
修改字典中的值
类比列表的操作,直接复制即可,不多做解释。
删除键-值对
用del
语句,类比列表的删除操作,是永久删除:
student = {'name': 'wang', 'age': 18}
del student['name']
print(student)
输出:
{'age': 18}
遍历所有键-值对
items()
items()
是字典的一个方法,返回一个键-值对列表。
开始遍历
用for
循环:
student = {'name': 'wang', 'age': 18}
for key, value in student.items():
print(key + ' : ' + str(value))
输出:
age : 18
name : wang
遍历字典中的所有键
keys()
此方法返回饱含字典的所有键的列表。
student.keys()
顺序遍历键
用keys()
方法获取到的键的列表,其中的顺序 是不确定的。
可以用列表的sort()
或sorted()
方法排序后,再进行操作。
遍历字典中所有的值
values()
此方法返回包含所有值的列表。
set()
集合set
类似于列表但是其中每个元素都必须独一无二。
字典中的值可能相同,当要取得独一无二的值的时候,用`set()
函数:
fruits = {'wang': 'peach', 'li': 'apple','zhang': 'peach', 'sun' : 'orange'}
for value in set(fruits.values()):
print(value)
输出:
apple
orange
peach
嵌套
字典列表
例如,一个字典包含一个人的信息,一个列表包含多个人的信息:
student_1 = {'name': 'wang', 'age': 18}
student_2 = {'name': 'li', 'age': 18}
student_3 = {'name': 'sun', 'age': 18}
students = [student_1, student_2, student_3]
print(students)
输出:
[{'name': 'wang', 'age': 18}, {'name': 'li', 'age': 18}, {'name': 'sun', 'age': 18}]
在字典中存储列表
比如学生有姓名、年龄也有他喜欢的水果:
student = {
'name': 'wang',
'age': 18,
'fruits': ['lemon', 'apple', 'banana', 'peach', 'strawberry']
}
for fruit in student['fruits']:
print(fruit)
输出:
lemon
apple
banana
peach
strawberry
在字典中存储字典
比如有一群学生,按学号来作为键,存储对应学号的学生:
students = {
'1611650628': {'name': 'wang', 'age': 18},
'1611650629': {'name': 'li', 'age': 18},
'1611650630': {'name': 'sun', 'age': 18}
}
print(students['1611650628']['name'])
输出:
wang
用户输入和while循环
input()
函数input()
接收一个参数,即要向用户显示的提示或说明,要让用户该知道如何做。
例:
fruit = input("What is your favorite fruit? ")
print("Yeah, now I know you love " + fruit + ".")
输出:
What is your favorite fruit? peach #peach为输入
Yeah, now I know you love peach.
int()
类似于之前讲的str()
,int()
将字符串变为数字。
例:
age = input("How old are you? ")
if age >= 18:
print("OK, come in.")
报错:
TypeError: unorderable types: str() >= int()
修改:
age = input("How old are you? ")
age = int(age)
if age >= 18:
print("OK, come in.")
输出:
How old are you? 18
OK, come in.
while循环
格式:
while 条件:
statement....
函数
定义函数
def 函数名():
statement.....
例:
def say_hello():
print("Hello!")
say_hello() #调用函数
输出:
Hello!
实参和形参
类比C语言中的实参和形参。
形参获得实参的值,是个副本。
例:
def change(number):
number = number + 1
print(number)
num = 2
change(2)
print(num)
输出:
3
2
传递实参
位置实参
调用函数时,Python必须将函数调用中的每个实参都关联到函数定义中的一个形参。为此,最简单的关联方式是基于实参的顺序。这种关联方式被称为位置实参。
说得这么复杂,其实就是对号入座的意思,讲那么麻烦。
关键字实参
关键字实参是传递给函数的 名称-值对。
关键字实参让你无需考虑实参的顺序,因为直接在实参中将名称和值关联起来了,这样还清楚地指出了函数调用中各个值的用途。
例:
def show(first, last):
print("first: " + first)
print("last: " + last)
show(last='Wang', first='Zhenkui')
输出:
first: Zhenkui
last: Wang
默认值
即,在编写函数时,给每个形参指定默认值。
之前的pop()
方法和range()
函数。
pop()
的参数的默认值为-1
,所以我们调用时,若不指定实参,就将列表最后一个元素弹出。
range()
的第三个参数默认值为1
,若不指定,便是每一步加1
。
例:
def show(first, last='Li'):
print(first + ' ' + last)
show(first='Zhenkui')
show(last='Wang', first='Zhenkui')
show('Zhenkui')
show('Zhenkui','Wang')
输出:
Zhenkui Li
Zhenkui Wang
Zhenkui Li
Zhenkui Wang
上述三种可以混合使用
让实参变为可选的
有时候,需要让实参变成可选的,这样使用函数的人就只需在必要时才提供额外的信息。要实现这个功能可以利用默认值。
例如,一个函数接收信息,姓名 以及对象的名字,但并不是每个人都有对象,比如我就没有。
可以给实参 double_elephant
指定一个默认值—-空字符串,在用户没有提供值时不使用这个实参, 并将其移到形参列表的末尾:
例:
def show(name, double_elephant = ''):
print("Welcome, " + name + '.')
if double_elephant:
print("You have a great double_elephant!")
print("Nice to meet you! " + double_elephant + ".")
show("Wang")
show("Wang", 'Who?')
输出:
Welcome, Wang.
Welcome, Wang.
You have a great double_elephant!
Nice to meet you! Who?.
返回值
就是return
,可以返回任何类型的值。
传递列表
在函数中修改列表
就像C语言传递数组一样。
在函数中修改列表时,修改的是列表本身。
之前讲列表复制的时候说两个列表变量不能用=
直接赋值,会让两个变量指向同一个列表,类比C语言的指针 和 Java 的引用类型,实参给形参传值的时候,形参也指向了同一个列表,在函数中修改时,修改的就是列表本身。
例:
def change(lists):
lists = lists.reverse()
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
change(fruits)
print(fruits)
输出:
['strawberry', 'peach', 'banana', 'apple', 'lemon']
禁止函数修改列表
但有时候我们并不希望函数修改原列表,可能需要备案之类的。这家店好吃,我吃过了还想吃嘛,再来一碗。
又是列表的复制,老知识,直接给他个切片不就完了。
同上例:
def change(lists):
lists = lists.reverse()
fruits = ['lemon', 'apple', 'banana', 'peach', 'strawberry']
change(fruits[:])
print(fruits)
输出:
['lemon', 'apple', 'banana', 'peach', 'strawberry']
传递任意数量的实参
类似Java的可变参数。
在形参的前面加一个星号*
。
就像Java中会为可变参数创建一个数组来存放一样,星号*
让Python创建一个名字同形参的元组,并将收到的所有值都封装到元组中。
结合使用位置实参和任意数量实参
例:
def show(name, *fruits):
print(name.title() + " likes:")
for fruit in fruits:
print(fruit)
show('wang', 'peach', 'banana', 'pineapple')
输出:
Wang likes:
peach
banana
pineapple
使用任意数量的关键字实参
有时候,需要接受任意数量的实参,但与先不知道传递给函数的会是什么样的信息。
可让函数编写成能够接受任意数量的键-值对—-调用语句提供了多少就接受多少。
这个时候,用的是两个星号**
,创建的不是元组,是字典。
例如,函数创建一个包含学生信息的字典:
def init_student(name, **info):
profile = {}
profile['name'] = name
for key, value in info.items():
profile[key] = value
return profile
student_1 = init_student('wang', age = 18, id = '1611650628')
print(student_1)
输出:
{'id': '1611650628', 'age': 18, 'name': 'wang'}
注意:记得加items()
还有,传递实参的时候,键 不用加引号。
将函数存储在模块中
模块
模块是扩展名为 .py 的文件,包含导入到程序中的代码。
import语句导入整个模块
以上面的代码为例:
t1.py
def init_student(name, **info):
profile = {}
profile['name'] = name
for key, value in info.items():
profile[key] = value
return profile
t2.py
import t1
student_1 = t1.init_student('wang', age = 18, id = '1611650628')
print(student_1)
输出同上,调用init_student
要在前面加上所属的模块名。
导入特定的函数
格式:
from module_name import function_name
修改上例的 t2.py:
from t1 import init_student
student_1 = init_student('wang', age = 18, id = '1611650628')
print(student_1)
输出相同。
使用 as 给模块指定别名
例:
t2.py
import t1 as T
student_1 = T.init_student('wang', age = 18, id = '1611650628')
print(student_1)
使用 as 给函数指定别名
例:
t2.py
from t1 import init_student as init
student_1 = init('wang', age = 18, id = '1611650628')
print(student_1)
导入全部函数
格式:
from module_name import *
类
创建和使用类
创建Human类
class Human():
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
print("Hello!")
方法__init__()
类似Java和PHP中的构造函数。
功能和其一样,不写了。
形参self
类中的方法定义时,形参self
必不可少,还必须为与其他形参的前面。
Python调用方法时,将自动传入实参self
,它是一个指向实力本身的引用,让实例能够访问类中的属性和方法。
类中变量定义
上例定义的两个变量都有一个前缀self
。
以self
为前缀的变量都可供类中的所有方法使用,还可以通过类的任何实例来访问这些变量。
创建实例
man = Human('wang', age = 18)
访问属性
即使用点运算符.
:
print(man.name)
输出:
wang
调用方法
man.speak()
输出:
Hello!
继承
创建子类时,父类必须包含在当前文件中,且位于子类前面。
定义子类时,必须在括号内指定父类的名称。
class Human():
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
print("Hello!")
class Man(Human):
def __init__(self, name, age):
super().__init__(name, age)
super()
super()
是一个特殊的函数,帮助Python将父类与子类关联起来。
上例的super().__init__(name, age)
调用了父类的__init__()
方法。
给子类添加属性和方法
假设男人有胡子的长度,女人没有…………
class Man(Human):
def __init__(self, name, age, beard_size):
super().__init__(name, age)
self.beard_size = beard_size
def show_beard_size(self):
print(self.beard_size)
添加一个胡子长度的属性和显示胡子长度的方法。
重写
假设这个男的是中国人,“全世界都在讲中国话~~~”:
class Man(Human):
#snip……
def speak(self):
print("你好!")
将实例用作属性
其实就像是Java里的在类中实例化另一个类,作为自己的成员。
不讲了。
导入类
导入单个类
格式:
from module_name import class_name
导入多个类
用逗号分隔:
from module_name import class_name_1,class_name_2.....
导入多个函数与此类似。
导入全部类
类比上面的函数的导入。
Python标准库
Python 标准库 是一组模块。
OrderedDict
如字面意思,有序的字典。
行为与字典相同,区别只在于记录了键-值对的添加顺序。
例:
from collections import OrderedDict
favorite_fruits = OrderedDict()
favorite_fruits['wang'] = 'peach'
favorite_fruits['li'] = 'apple'
favorite_fruits['sun'] = 'orange'
for name,fruit in favorite_fruits.items():
print(name + " \t >>> \t" + fruit)
输出:
wang >>> peach
li >>> apple
sun >>> orange
#按添加的顺序输出
文件和异常
从文件中读取数据
打开文件
格式:
with open(filename) as file_object:
#snip
open()
函数open()
接收一个参数:要打开的文件的名称,或绝对路径。
返回一个表示文件的对象,Python将其存放在后面使用的变量中。
with()
关键字with
在不再需要访问文件后将其关闭,很方便的功能。
上例只调用了open()
,没有调用close()
。
如果程序有bug,倒是close()
未执行,文件将不会关闭。
若过早关闭,也会造成错误。
所以,让Python自动去确定关闭文件的时机会更好。
读取整个文件
首先要有一个被读取的文件:
poem.txt
《夜雨》
白居易
我有所念人,隔在远远乡。
我有所感事,结在深深肠。
乡远去不得,无日不瞻望。
肠深解不得,无夕不思量。
况此残灯夜,独宿在空堂。
秋天殊未晓,风雨正苍苍。
不学头陀法,前心安可忘。
我很喜欢这首诗,非常喜欢,在表白失败之后遇到的,很巧,所以非常喜欢。
with open('poem.txt',encoding='utf-8') as file:
contents = file.read()
print(contents)
输出:
《夜雨》
白居易
我有所念人,隔在远远乡。
我有所感事,结在深深肠。
乡远去不得,无日不瞻望。
肠深解不得,无夕不思量。
况此残灯夜,独宿在空堂。
秋天殊未晓,风雨正苍苍。
不学头陀法,前心安可忘。
最后多出一个空行,因为read()
到达文件末尾时返回一个空字符串,而将这个空字符串显示出来时就是一个空行。
删除空行可以用rstrip()
。
还有上面open()
中我加了一个encoding = 'utf-8'
,如果不写就会出现错误:
UnicodeDecodeError: 'gbk' codec can't decode byte 0xa4 in position 11: illegal multibyte sequence
就是gbk
解码不了,有中文嘛,所以就用万国码utf-8
吧。
文件路径
和Java类似,有相对路径与绝对路径。
相对路径:直接写文件名,在相对于当前运行的程序所在目录中找到文件并打开。
绝对路径:就是在系统中的存放路径。如:'C:\User\ehmatthes\ohther_files\text_files\filename.txt'
。
逐行读取
可以把上例的file
当成一个元组,文件中每一列对应元组中一个元素:
with open('poem.txt',encoding='utf-8') as file:
for line in file:
print(line)
输出:
《夜雨》
白居易
我有所念人,隔在远远乡。
我有所感事,结在深深肠。
乡远去不得,无日不瞻望。
肠深解不得,无夕不思量。
况此残灯夜,独宿在空堂。
秋天殊未晓,风雨正苍苍。
不学头陀法,前心安可忘。
每行都有空白,每行的末尾都有一个换行符。print()
函数也会加上换行符,所以多出一个空行。
readlines()
获得一个包含文件每行的的列表。
with open('poem.txt',encoding='utf-8') as file:
for line in file.readlines():
print(line.rstrip())
输出:
《夜雨》
白居易
我有所念人,隔在远远乡。
我有所感事,结在深深肠。
乡远去不得,无日不瞻望。
肠深解不得,无夕不思量。
况此残灯夜,独宿在空堂。
秋天殊未晓,风雨正苍苍。
不学头陀法,前心安可忘。
in语句也可以用在一个小字符串是否在一个大字符串中
replace()
将字符串中的一个特定单词都换成另一个单词。
例:
message = "I love apple."
message = message.replace('apple','peach')
print(message)
输出:
I love peach.
多次调用write()
不会换行,若要换行在字符串末尾加上\n
。
写入文件
open()
调用open()
函数时,还可以指定第二个参数。
和C语言类似。
字母 | 模式 |
---|---|
‘w’ | 写入模式 |
‘r’ | 读取模式 |
‘a’ | 附加模式 |
‘r+’ | 读写模式 |
以写模式打开文件,如果文件已存在,Python将在返回文件对象前清空该文件。
注意:Python只能将字符串写入文件。要将数值存入文本,必须先使用函数str()
将其转换为字符串格式。
异常
try-except代码块
也就是类似Java和PHP的try-catch。
try:
#snip
except Exception_name:
#snip
处理ZeroDivisionError异常
字面意思,就是程序“除0”了。
这么干真蠢,但也是可能的呀。
例如有一个除法计算功能的程序:
print("Give me two numbers, and I 'll divide them.")
print("Enter 'q' to quit")
while True:
f_number = input("First number: ")
if f_number == 'q':
break
l_number = input("Second number: ")
if l_number == 'q':
break
result = int(f_number)/int(l_number)
print(result)
当我们将第二个数输入为0时:
Give me two numbers, and I 'll divide them.
Enter 'q' to quit
First number: 1
Second number: 0
Traceback (most recent call last):
File "D:/PyCharm 2017.1.5/项目/t1.py", line 13, in <module>
result = int(f_number)/int(l_number)
ZeroDivisionError: division by zero
然后这程序就挂了。
else代码块
依赖于try代码块成功执行的代码都应该放在else中:
print("Give me two numbers, and I 'll divide them.")
print("Enter 'q' to quit")
while True:
f_number = input("First number: ")
if f_number == 'q':
break
l_number = input("Second number: ")
if l_number == 'q':
break
try:
result = int(f_number)/int(l_number)
except ZeroDivisionError:
print("You can't divide by 0! ")
else:
print(result)
输出:
Give me two numbers, and I 'll divide them.
Enter 'q' to quit
First number: 1
Second number: 0
You can't divide by 0!
First number:
处理FileNotFoundError异常
就是找不到文件,如果没找到,你咋办咋办。
split()
以空格为分隔符将字符串拆分成各个部分,存在列表中。
string = "I love peach"
list = string.split()
print(list)
输出:
['I', 'love', 'peach']
储存数据
使用json.dump和json.load
函数json,dump()
接受两个参数:要存储的数据以及可用于存储数据的文件对象。
import json
number= [2, 3, 3, 3, 3, 3]
filename = 'p.json'
with open(filename,'w') as file:
json.dump(number,file)
p.json
[2, 3, 3, 3, 3, 3]
函数接收一个参数,可读取的文件对象。
import json
filename = 'p.json'
with open(filename,'r') as file:
list = json.load(file)
print(list)
输出:
[2, 3, 3, 3, 3, 3]
示例,用户输入自己的名字,然后再次运行程序时显示TA的名字:
import json
filename = 'username.json'
try: #若文件存在就加载它
with open(filename,'r') as file:
username = json.load(file)
except FileNotFoundError: #若文件不存在就提示用户输出入
username = input("What's your name: ")
with open(filename,'w') as file:
json.dump(username,file)
print("We'll show your name when you come back.")
else:
print("Welcome! " + username + '.')
输出:
第一次
What's your name: wang
We'll show your name when you come back.
第二次
Welcome! wang.
文档字符串
就是在函数或者类的开头标明函数和类的功能、如何使用以及参数规范等信息。
格式:
"""---snip---"""
测试代码
测试函数
单元测试和测试用例
Python标准库中的模块unittest提供了代码测试工具。
单元测试用于核实函数的某个方面没有问题,测试用例是一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求。
良好的测试用例考虑到了函数可能收到的各种输入,包含针对所有这些情形的测试。
全覆盖式测试用力考虑到了可能收到的各种输入,涵盖了各种可能的函数使用方式。
对于大型项目,要实现全覆盖可能很难。通常,最初只要针对代码的重要行为进行编写测试即可,等项目被广泛使用时再考虑全覆盖。
可通过的测试
要为函数写测试用例,先导入模块unittest以及要测试的函数,在创建一个继承unittest.TestCase
的类,并编写一系列方法对函数行为的不同方面进行测试。
比如现在有一个函数get_formatted_name()
接受两个参数,名和姓,返回格式整洁的全名:
name_function.py
def get_formatted_name(first, last):
"""Generate a neatly formatted full name."""
full_name = first + " " + last
return full_name.title()
test_name_function.py:
import unittest
from name_function import get_formatted_name
class NameTestCase(unittest.TestCase):
"""测试name_function.py"""
def test_first_last_name(self):
formatted_name = get_formatted_name('zhenkui', 'wang')
self.assertEqual(formatted_name,'Zhenkui Wang')
unittest.main()
首先创建一个名为NameTestCase
的类,用于包含一系列针对get_formatted_name()
的单元测试。当然可以随便命名,但最好这么写。这个类必须继承unittest.TestCase
类,这样Python才能知道如何运行你编写的测试。
此类现在只包含一个方法,用于测试get_formatted_name()
的一个方面。此方法要核实的是 只有名和姓的姓名能否被正确地格式化。运行test_name_function.py
时,所有以test_
来头的方法都会自动执行。
断言测试
断言方法用来核实得到的结果书否与期望的结果一致。在这里,我们知道get_formatted_name()
应该返回这样的姓名,即名和姓的首字母大写,且它们之间有一个空格,因此我们希望formatted_name
的值为Zhenkui Wang
。
self.assertEqual(formatted_name,'Zhenkui Wang')
的意思是,如果formatted_name
的值和字符串'Zhenkui Wang'
相等,就通过测试,否则告我一声。
unittest.main()
让Python运行这个文件中的测试。
输出:
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
还可以添加新测试,即往测试类中添加测试方法
测试类
断言方法
Python在unittest.TestCase
类中提供了很多断言方法。
常用的6个断言方法:
方法 | 用途 |
---|---|
assertEqual(a, b) | 核实a == b |
assertNotEqual(a, b) | 核实a != b |
assertTrue(x) | 核实x为True |
assertFalse(x) | 核实x为False |
assertIn(item, list) | 核实 item 在 list 中 |
assertNotIn(item, list) | 核实 item 不在 list 中 |
方法setUp()
进行测试,如测试类的时候,总要将类实例化,每个测试方法都要实例化一遍,显得有些繁杂。
如果在测试类中包含了setUp()
方法,Python将会先运行它,然后再运行以test_
打头的方法。
这样,在编写的每个测试方法中就都可以使用在setUp()
中创建的对象。