《Python编程从入门到实践》笔记3 ( 9.类 10.文件和异常 11.测试代码)

第9章 类

9.1 创建和使用类

9.2 使用类和实例

        9.2.1 Car类
        9.2.2 给属性指定默认值
        9.2.3 修改属性的值

class Car():
    """一次模拟汽车的简单尝试"""
    def __init__(self, make, model, year):
        """初始化汽车的描述性信息"""
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0 #为属性指定默认值
  
    def get_descriptive_name(self):
        """返回整洁的描述信息"""
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()

    def read_odometer(self):
        """打印指出汽车的里程信息"""
        print("This car has " + str(self.odometer_reading) + " miles on it.")

    def update_odometer(self, mileage):
        """设置里程表"""
        self.odometer_reading = mileage

#每个与类相关联的方法 调用都自动传递实参 self 
#它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。

my_new_car = Car('audi', 'a4', 2019)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()
my_new_car.odometer_reading = 23 #直接修改属性的值
my_new_car.read_odometer()
my_new_car.update_odometer(100)
my_new_car.read_odometer()


9.3 继承
        9.3.1 子类的方法__init__()
        9.3.2 Python 2.7中的继承
        9.3.3 给子类定义属性和方法
        9.3.4 重写父类的方法
        9.3.5 将实例用作属性
        9.3.6 模拟实物

car.py

class Battery():
    """模拟电瓶"""
    def __init__(self, battery_size=70):
        self.battery_size = battery_size
    
    def describe_battery(self):
        print("This car has a " + str(self.battery_size) + "-kWh battery.")

class ElectricCar(Car):
    """电动汽车独特之处"""
    def __init__(self, make, model, year):
        """初始化父类的属性"""
        super().__init__(make, model, year)
        self.battery_size = 70
        self.battery  = Battery() # 将实例用作属性
        
        #python2.7 中的继承
        #父类定义指定object
        #class Car(object):
        #super(ElectricCar, self).__init__(make, model, year)
        
    def describe_battery(self):
        print("This Eclectric car has a " + str(self.battery_size) + "_kWh battery.")

    #重写父类方法
    def get_descriptive_name(self):
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model + ' ' + str(self.battery_size) + 'kwh'
        return long_name.title()

#我们定义了一个名为 Battery 的新类, 这看似做了很多额外的工作,但现在我们想多详细地描述电瓶都可以,且不会导致 ElectricCar
#类混乱不堪。可以再给 Battery 类添加一些方法


my_tesla = ElectricCar('tesla', 'model s', 2019)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
my_tesla.battery.describe_battery()


9.4 导入类
        9.4.1 导入单个类

from car import Car

my_new_car = Car('audi', 'a4', 2018)
print(my_new_car.get_descriptive_name())

my_new_car.odemeter_reading = 23
my_new_car.read_odometer()

        9.4.2 在一个模块中存储多个类

from car import ElectricCar
my_tesla = ElectricCar('tesla', 'model s', 2016)

my_tesla.battery.describe_battery()

        9.4.3 从一个模块中导入多个类

from car import Car, ElectricCar
my_beetle = Car('volkswagen', 'beetle', 2016)

my_tesla = ElectricCar('tesla', 'roadster', 2016)

        9.4.4 导入整个模块

import car
my_beetle = car.Car('volkswagen', 'beetle', 2016) 5

my_tesla = car.ElectricCar('tesla', 'roadster', 2016)

        9.4.5 导入模块中的所有类

from module_name import *

不推荐, 导入类不明确, 还有可能有同名问题

需要从一个模块中导入很多类时,最好导入整个模块,并使用 module_name.class_name 语法
来访问类


        9.4.6 在一个模块中导入另一个模块

#electric_car.py
from car import Car
class Battery():
-- snip --
class ElectricCar(Car):
-- snip --
#my_car.py
from car import Car  #一个Car 类 单独文件
from electric_car import ElectricCar #导入car的子类
my_beetle = Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())

        9.4.7 自定义工作流程


9.5 Python标准库

创建字典并记录其中的键—值对的添加顺序,可使用模块 collections 中的 OrderedDict 类

from collections import OrderedDict

favorite_languages = OrderedDict()

favorite_languages['jen'] = 'python'
favorite_languages['sarah'] = 'C'
favorite_languages['edward'] = 'ruby'
favorite_languages['phih'] = 'python'

for name, language in favorite_languages.items():
    print(name.title() + "'s favorite language is " + language.title() + '.')


9.6 类编码风格

  • 类名应采用驼峰命名法
  • 实例名和模块名都采用小写格式,并在单词之间加上下划线
  • 对于每个类,都应紧跟在类定义后面包含一个文档字符串,对其中的类可用于做什么进行描述
  • 空行,在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。
  • 需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的 import 语句,再添加一个空行,然后编写导入你自己编写的模块的 import 语句


9.7 小结

 

第10章 文件和异常


10.1 从文件中读取数据

        10.1.1 读取整个文件

with open('pi_digit.txt') as file_object:  #关键字 with 在不再需要访问文件后将其关闭
    contents = file_object.read()
    print(contents)

        10.1.2 文件路径

linux ------ with open('text_files/ filename .txt') as file_object:

windows 反斜杠 -------with open('text_files\ filename .txt') as file_object:
        10.1.3 逐行读取

with open('pi_digit.txt') as file_object:
    for line in file_object:
        print(line.restrip())  #restrip 要消除这些多余的空白行, 否则有每句结尾有空行

        10.1.4 创建一个包含文件各行内容的列表

filename = 'pi_digit.txt'
with open(filename) as file_object:
    lines = file_object.readlines()

for line in lines:
    print(line.rstrip())

        10.1.5 使用文件的内容
        10.1.6 包含一百万位的大型文件

filename = 'pi_million_digits.txt'
with open(filename) as file_object:
    lines = file_object.readlines()

pi_string = ''
for line in lines:
    pi_string += line.strip()

print(pi_string[:52] + "...")
print(len(pi_string))


        10.1.7 圆周率值中包含你的生日吗

10.2 写入文件

        10.2.1 写入空文件
        10.2.2 写入多行

# r, w, a ,r+ 几种模式
filename = 'programming.txt'
with open(filename, 'w') as file_object:
    file_object.write("I love programming.")
    file_object.write("I love creating new games.")

        10.2.3 附加到文件

如果你要给文件添加内容,而不是覆盖原有的内容,可以附加模式打开文件

open(filename, 'a')

10.3 异常

        10.3.1 处理ZeroDivisionError异常
        10.3.2 使用try-except 代码块
        10.3.3 使用异常避免崩溃
        10.3.4 else 代码块

print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")

while True:
    first_number = input('\nFirst number: ')
    if first_number == 'q':
        break
    second_number = input("Second number:")
    if second_number == 'q':
        break
    
    try:
        answer = int(first_number) / int(second_number)
    except ZeroDivisionError:
        print("You can't divide by 0!")
    else:
        print(answer)


        10.3.5 处理FileNotFoundError异常
        10.3.6 分析文本 split 函数,分割文本, 存储为列表
        10.3.7 使用多个文件

def count_words(filename):
    """计算一个文件包含多少个单词"""
    try:
        with open(filename) as f_obj:
            contents = f_obj.read()
    except FileNotFoundError:
        msg = "Sorry, the file " + filename + "dost not exist."
        print(msg)
    else:
        # 计算文件大致包含多少个单词
        words = contents.split()
        num_words = len(words)
        print("The file " + filename + " has about " + str(num_words) + " words.")

filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
for filename in filenames:
count_words(filename)

#使用 try-except 代码块提供了两个重要的优点:避免让用户看到traceback;
#让 程 序 能 够 继 续 分 析 能 够 找 到 的 其 他 文 件

        10.3.8 失败时一声不吭  pass

try:
--snip--
except FileNotFoundError:
pass


        10.3.9 决定报告哪些错误

如用户输入、存在指定的文件、有网络链接,就有可能出现异常

控制与用户分享错误信息的程度

10.4 存储数据

模块 json 让你能够将简单的Python数据结构转储到文件中,并在程序再次运行时加载该文件中的数据

        10.4.1 使用json.dump()和json.load()

import json 

numbers = [2,3,5,7,11,13]
#wirte
with open('numbers.json', 'w') as f_obj:
    json.dump(numbers, f_obj)

#read
with open('numbers.json') as f_obj:
    numberlist = json.load(f_obj)

print(numberlist)


        10.4.2 保存和读取用户生成的数据
        10.4.3 重构

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():
    """问候用户,并指出其名字"""
    filename = 'username.json'
    username = get_stored_username()
    if username:
        print("Welcome back, " + username + "!")
    else:
        username = get_new_username()
        print("We'll remember you when you come back," + username)

greet_user()


第11章 测试代码


11.1 测试函数

    11.1.1 单元测试和测试用例
    11.1.2 可通过的测试
    11.1.3 不能通过的测试
    11.1.4 测试未通过时怎么办
    11.1.5 添加新测试

使用Python模块 unittest 中的工具来测试代码.

要为函数编写测试用例,可先导入模块 unittest 以及要测试的函数,

再创建一个继承 unittest.TestCase 的类,并编写一系列方法对函数行为的不同方面进行测试。

name_function.py

def get_formatted_name(first, last, middle=''):
    """Generate a neatly formatted full name."""
    if middle:
        full_name = first + ' ' + middle + ' '+ last
    else:
        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):
    """test name_function.py"""
    
    def test_first_last_name(self):
        formatted_name = get_formatted_name('janis', 'joplin')
        self.assertEqual(formatted_name, 'Janis Joplin')
    def test_first_last_middle_name(self):
        formatted_name = get_formatted_name('wolfgang', 'mozart', 'amadeus')
        self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart')

unittest.main()

 

11.2 测试类

    11.2.1 各种断言方法

  • 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 中


    11.2.2 一个要测试的类
    11.2.3 测试AnonymousSurvey类
    11.2.4 方法setUp()

可在 setUp() 方法中创建一系列实例并设置它们的属性,再在测试方法中直接使用这些实例。相比于在每个测试方法中都创
建实例并设置其属性,这要容易得多

survey.py


class AnonymousSurvey():
    """手机匿名调查问卷的答案"""
    
    def __init__(self, question):
        """存储一个问题, 并未存储答案做准备"""
        self.question = question
        self.responses = []
    
    def show_question(self):
        """显示调查问卷"""
        print(self.question)
    
    def store_response(self, new_response):
        """存储单份调查答卷"""
        self.responses.append(new_response)
    
    def show_results(self):
        """显示收集到的所有答卷"""
        print("Survey results:")
        for response in self.responses:
            print('- ' + response)

 

test_survey.py

import unittest
from survey import AnonymousSurvey

class TestAnonmyousSurvey(unittest.TestCase):
    """test for class anonymousSurvey"""
    
    #如果你在 TestCase 类中包含了方法 setUp() ,Python将先运行它,再运行各个以test_打头的方法。
    def setUp(self):
        """
        创建一个调查对象和一组答案,供使用的测试方法使用
        """
        question = "What language did you first learn to speak?"
        self.my_survey = AnonymousSurvey(question)
        self.responses = ['English', 'Spanish', 'Mandarin']
        
    def test_store_sinlge_response(self):
        """测试单个答案会被妥善地存储"""
        question = "What language did you first learn to speak?"
        self.my_survey.store_response(self.responses[0])
        self.assertIn(self.responses[0], self.my_survey.responses)
        
    def test_store_three_responses(self):
        """测试三个答案会被妥善地存储"""
        for response in self.responses:
            self.my_survey.store_response(response)
            
        for response in self.responses:
            self.assertIn(response, self.my_survey.responses)
            
            
unittest.main()

 

你可能感兴趣的:(python)