十、十一章总结
第十章
第十章的内容有读取文件,写入文件,异常和使用.json格式存储数据
1.读取文件
"""以绝对路径读取文件并用直接读取,遍历文件,存储列表的方式打印"""
file_name = r'E:\python\python_work\chapter_10\learning_python.txt'
with open(file_name) as file_object:
contents = file_object.read()
print(contents.rstrip()) #.rstrip()去除结尾的换行
print('') #使用\n会换两行
with open(file_name) as file_object:
for line in file_object:
print(line.rstrip())
print('')
with open(file_name) as file_object:
lines = file_object.readlines()
for line in lines:
print(line.rstrip())
file_name我给了完整的路径,windows的路径用反斜杠‘\’分隔,因为’'也表示转义标记,前面的r表示后面内容为原始字符串,只提供文件名打开和保存都是在所打开的文件夹下。
上面的代码使用with open打开了三次文件,分别读取整个文件,逐行读取,创建一个包含各行内容的列表。并且分别打印了一次内容。
2.写入文件
文件打开方式有 r w a r+
‘r’ | 读取模式 |
‘w’ | 写入模式 |
‘a’ | 附加模式 |
‘r+’ | 读写模式 |
如果没有指定,则默认为读取模式。
(1)写入模式
写入模式下,如果文件已经存在则会在返回文件对象前清空该文件。
"""使用w模式将输入的文本依次写入文件"""
file_name = r'E:\python\python_work\text_files\guest.txt'
with open(file_name, 'w') as f_obj:
while 1:
name = input("Enter a name (enter q to close ): ")
if name.lower() == 'q':
break
else:
print("welcome! " + name.title() + '!')
f_obj.write(name.title() + '\n')
(2)附加模式
写入的内容会附加到文件末尾。若指定文件不存在则创建一个空文件。
"""使用a模式将输入的文本依次写入文件"""
file_name = r'E:\python\python_work\text_files\reasons.txt'
with open(file_name, 'a') as f_obj:
while 1:
reason = input("Enter you reason (enter q to close ): ")
if reason.lower() == 'q':
break
else:
f_obj.write(reason + '\n')
(3)替换函数
"""以绝对路径读取文件,并用replace将python改为c"""
file_name = r'E:\python\python_work\chapter_10\learning_python.txt'
with open(file_name) as file_object:
contents = file_object.read()
print(contents.replace('python', 'c'))
使用replace函数将内容中的python替换为c。
3.异常
类似于C,matlab的try,catch。python使用try,except,else处理异常。
但是有意思的是except需要指定异常的类型。若没有异常,则运行else中的内容。
(1)遇到异常时提示
"""编写一个函数,计算两个数字相加。如果相加时出现字符则提示"""
def add_fun():
print('enter q to quit.')
while 1:
num1 = input('\nenter first num: ')
if num1 == 'q':
break
num2 = input('\nenter second num: ')
if num2 == 'q':
break
try:
answer = int(num1) + int(num2)
print("\nanswer equal " + str(answer))
except ValueError:
print("请输入数字!")
add_fun()
输入数字进行相加时,输入的是字符要先用int转为数字
(2)遇到异常时沉默
"""编写读取文件并屏幕打印函数,找不到文件时沉默pass"""
def file_read(filename):
try:
with open(filename) as pet1:
pet1names = pet1.readlines()
for name in pet1names:
print(name)
except FileNotFoundError:
pass
filename = r'E:\python\python_work\text_files\cats.txt'
filename2 = r'E:\python\python_work\text_files\dogs.txt'
file_read(filename)
file_read(filename2)
4.使用.json存储数据
.json格式不是python专用的,因此可以与其他语言共享。
使用时需要先导入json模块,使用json.dump(),json.load()分别保存和读取。
"""使用a模式写入json文件,并读取打印"""
import json
filename = 'numbers.json'
while 1:
with open(filename, 'a') as f_obj:
number = input('enter a num: ')
if number == 'q':
break
else:
json.dump(int(number),f_obj)
with open(filename) as f_obj:
numbers = json.load(f_obj)
print(numbers)
上面的程序练习了使用dump与load。
"""练习10-13"""
import json
def get_stored_username():
"""如果存储,读取并返回"""
filename = 'username.json'
try:
with open(filename) as f_obj:
username = json.load(f_obj)
except FileNotFoundError:
return None
else:
return username
def get_new_username():
"""提示用户输入姓名"""
username = input("what is your name? ")
filename = 'username.json'
with open(filename, 'w') as f_obj:
json.dump(username, f_obj)
return username
def greet_user():
"""问候用户"""
username = get_stored_username()
if username:
check = input("does " + username + " is you name?(y/n)")
if check.lower() == 'y':
#判断是否为老用户,不是则输入新用户名
print("welcome back, " + username + "!")
else:
username = get_new_username()
print("we'll remember you when you come back, " + username + "!")
else:
username = get_new_username()
#这里如果错误使用get_stored_username会出现类型错误,username类型为None
print("we'll remember you when you come back, " + username + "!")
greet_user()
以上的程序修改了书中的例子,首先书中对代码进行重构将各个功能分别写入各个函数中。通过greet_user对各函数进行调用,并增加判断是否为之前用户的功能。
第十一章
第十一章的内容为编写测试程序,这是我之前学习matlab或c语言没有遇到过的。测试可以测试函数和类,测试用例包含一组单元测试,单元测试用来核实函数的某方面没有问题。
编写测试函数时需要先导入测试模块unittest,并创建一个继承unittest.TestCase的子类。
1.测试函数
city_functions.py
def get_city_country_name(city, country, population=''): #11-1
"""获得城市,国家名并返回指定格式"""
if population:
information = city.title() + ', ' + country.title() + ' -population ' + population
else:
information = city.title() + ', ' + country.title()
return information
test_cities.py
import unittest #11-1
from city_functions import get_city_country_name
class CityTestCase(unittest.TestCase):
"""测试city_functions.py"""
def test_city_country(self):
"""测试不输入人口的情况"""
information = get_city_country_name('ponytowm', 'equstria')
self.assertEqual(information, 'Ponytowm, Equstria')
def test_city_country_population(self):
"""测试输入人口的情况"""
information = get_city_country_name('ponytowm', 'equstria', '123')
self.assertEqual(information, 'Ponytowm, Equstria -population 123')
unittest.main()
子类中的方法都含有test_前缀,这类方法不需要调用直接执行,通过unittest.main()进行测试,self.assertEqual为断言方法,判断两个参数是否相等。常用的断言方法有:
Equal,NotEqual,True,False,In,NotIn。
测试通过会显示如下内容。
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
第一行一个局点表示通过一个单元测试。测试引发错误显示E,断言失败时显示F。
单元测试的名称最后描述功能。
1.测试类
class Employee():
"""定义描述雇员的类"""
def __init__(self, first, last, salary):
"""初始化属性"""
self.first = first.title()
self.last = last.title()
self.salary = salary
def give_raise(self, amount=5000):
"""加薪方法,默认5000"""
self.salary += amount
#11-3
import unittest
from employees import Employee
class TestEmployee(unittest.TestCase):
"""测试默认加薪与给点加薪值能否运行"""
def setUp(self):
"""创建一个雇员实例存储在self的属性中以供该类中其他方法使用
给self一个属性amount=1,为测试给点加薪值
"""
self.employee1 = Employee('pinkie' , 'pie', 99999)
self.amount = 1
def test_give_default_raise(self):
"""默认5000测试"""
self.employee1.give_raise()
self.assertEqual(self.employee1.salary, 104999)
def test_give_custom_raise(self):
"""给定加薪值1测试"""
self.employee1.give_raise(self.amount)
self.assertEqual(self.employee1.salary, 100000)
unittest.main()
上面的程序对类进行测试,并通过**setUp(self)**建立一个作为self属性的实例,因此之后的单元测试可以直接对该实例的方法进行调用以测试,而无需在每个单元测试中创建实例。
至此该书的基础知识部分全部看完,还剩下项目学习,应该会很有趣。但编程的关键果然还在于多加练习,仅仅看了这些知识,学了后面前面就忘记的很多。