学习笔记

PythonChapter9~11笔记_2019-05-02

2019-05-02  本文已影响0人  AJohn11

Chapter9 类

1. 创建和使用类

1. 创建Dog类

class Dog():#首字母大写--类
    """一次模拟小狗的简单尝试"""

    def __init__(self, name, age):
        """初始化属性name和age"""
        self.name=name
        self.age=age

    def sit(self):
        """模拟小狗被命令蹲下"""
        print(self.name.title()+" is now sitting.")

    def roll_over(self):
        """模拟小狗被命令打滚"""
        print(self.name.title()+" rolled over!")
  1. 方法__init__()
  1. 在Python 2.7中创建类--括号内包含object
class ClassName(object):
    --snip--

2. 根据类创建实例

my_dog = Dog('willie', 6)
print("My dog's name is " + my_dog.name.title() + ".") 
print("My dog is " + str(my_dog.age) + " years old.")
  1. 访问属性
  1. 访问方法
  1. 创建多个实例

2. 使用类和实例

1. Car类

2. 给属性指定默认值

class Car(): 
    """一次模拟汽车的简单尝试"""
    def __init__(self, make, model, year): 
        """初始化描述汽车的属性"""
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0#默认值是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.")

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

输出:

2016 Audi A4
This car has 0 miles on it.

3. 修改属性的值

三种方式:

  1. 直接修改属性的值
  1. 通过方法修改属性的值
  1. 通过方法对属性值进行递增

总程序示例:

class Car(): 
    """一次模拟汽车的简单尝试"""
    def __init__(self, make, model, year): 
        """初始化描述汽车的属性"""
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0#默认值是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): 
        """将里程表读数设置为指定的值 禁止将里程表读数往回调"""
        if mileage >= self.odometer_reading:
            self.odometer_reading = mileage 
        else:
            print("You can't roll back an odometer!")
    def increment_odometer(self, miles): 
        """将里程表读数增加指定的量""" 
        self.odometer_reading += miles

my_new_car = Car('audi', 'a4', 2016) 
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(25) 
my_new_car.read_odometer()
my_new_car.update_odometer(22) 
my_new_car.read_odometer()

my_used_car = Car('subaru', 'outback', 2013) 
print(my_used_car.get_descriptive_name())
my_used_car.update_odometer(23500) 
my_used_car.read_odometer()
my_used_car.increment_odometer(100)
my_used_car.read_odometer()

输出:

2016 Audi A4
This car has 0 miles on it.
This car has 23 miles on it.
This car has 25 miles on it.
You can't roll back an odometer!
This car has 25 miles on it.
2013 Subaru Outback
This car has 23500 miles on it.
This car has 23600 miles on it.

3. 继承

1.子类的方法__init()__

class ElectricCar(Car): 
    """电动汽车的独特之处"""
    def __init__(self, make, model, year): 
        """初始化父类的属性"""
        super().__init__(make, model, year)

my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())

输出:

2016 Tesla Model S

2. Python 2.7中的继承

class Car(object):
    def __init__(self, make, model, year):
        --snip--
class ElectricCar(Car):
    def __init__(self, make, model, year):
        super(ElectricCar, self).__init__(make, model, year) 
        --snip--

3. 给子类定义属性和方法

class ElectricCar(Car): 
    """电动汽车的独特之处"""
    def __init__(self, make, model, year): 
        """电动汽车的独特之处 
        初始化父类的属性,再初始化电动汽车特有的属性 """
        super().__init__(make, model, year)
        self.battery_size = 70
    def describe_battery(self):
        """打印一条描述电瓶容量的消息"""
        print("This car has a " + str(self.battery_size) + "-kWh battery.")

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

输出:

2016 Tesla Model S
This car has a 70-kWh battery.

4. 重写父类的方法

5. 将实例用作属性

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.")
    def get_range(self): 
        """打印一条消息,指出电瓶的续航里程"""
        if self.battery_size == 70: 
            range = 240
        elif self.battery_size == 85: 
            range = 270
        message = "This car can go approximately " + str(range)
        message += " miles on a full charge." 
        print(message)

class ElectricCar(Car): 
    """电动汽车的独特之处"""
    def __init__(self, make, model, year): 
        """电动汽车的独特之处 
        初始化父类的属性,再初始化电动汽车特有的属性 """
        super().__init__(make, model, year)
        self.battery_size = 70
        self.battery = Battery()#用实例做属性
    def describe_battery(self):
        """打印一条描述电瓶容量的消息"""
        print("This car has a " + str(self.battery_size) + "-kWh battery.")
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()

输出:

2016 Tesla Model S
This car has a 70-kWh battery.
This car can go approximately 240 miles on a full charge.

6. 模拟实物

4. 导入类

1. 导入单个类

from car import Car

2. 在一个模块中存储多个类

3. 从一个模块中导入多个类

from car import Car, ElectricCar

4. 导入整个模块

5. 导入模块中的所有类

from module_name import *
不推荐

  1. 没有明确指出使用了哪些类
  2. 可能引发同名导致的错误。

6. 在一个模块中导入另一个模块

可以在一个模块中导入另一个模块中的类。

7. 自定义工作流程

5. Python标准库

6. 类编码风格

Chapter10 文件和异常

1. 从文件中读取数据

  1. 读取整个文件
    例:
with open('pi_digits.txt') as file_object: 
    contents = file_object.read() 
    print(contents)

输出:

3.1415926535
  8979323846
  2643383279

  1. 文件路径
    要让Python打开不与程序文件位于同一个目录中的文件 -- 需要提供文件路径。
  1. 逐行读取
filename='pi_digits.txt'
with open(filename) as file_object: 
    for line in file_object:#通过**执行循环**来**遍历文件中的每一行**
        print(line)

输出:

3.1415926535

  8979323846

  2643383279

  1. 创建一个包含文件各行内容的列表
filename = 'pi_digits.txt'
with open(filename) as file_object:
    lines = file_object.readlines()
    for line in lines: 
        print(line.rstrip())

输出:

3.1415926535
  8979323846
  2643383279
  1. 使用文件的内容
  1. 包含100万位的大型文件
  1. 圆周率值中包含你的生日吗
    例:
filename = '/Users/ligao/Desktop/python_work/《Python编程》源代码文件-更新/chapter_10/pi_million_digits.txt'
with open(filename) as file_object: 
    lines = file_object.readlines()
pi_string = ''
for line in lines:
    pi_string += line.rstrip()
    
birthday = input("Enter your birthday, in the form mmddyy: ") 
if birthday in pi_string:#**in**用法也可以是 字符串 in 字符串,即后一个字符串中是否包含前一个字符串 
    print("Your birthday appears in the first million digits of pi!") 
else:
    print("Your birthday does not appear in the first million digits of pi.")

输出:

Enter your birthday, in the form mmddyy: 031897
Your birthday appears in the first million digits of pi!

2. 写入文件

保存数据的最简单的方式 -- 写入到文件中。通过将输出写入文件,可以:

  1. 写入空文件
    例:
filename = 'programming.txt'
with open(filename, 'w') as file_object:
    file_object.write("I love programming.")

输出文件:

I love programming.
  1. 写入多行
  1. 附加到文件

3. 异常

  1. 处理ZeroDivisionError 异常(除数是0)
print(5/0)

输出:

Traceback (most recent call last):
  File "/Users/ligao/Desktop/python_work/Chapter10.py", line 38, in <module>
    print(5/0)
ZeroDivisionError: division by zero
  1. 使用try-except代码块
try: 
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")

输出:

You can't divide by zero!
  1. 使用异常避免崩溃
  1. else代码块

try-except-else 代码块的工作原理:

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

输出:

Enter 'q' to quit.

First number: 1
Second number: 2
0.5

First number: 3
Second number: 0
You can't divide by 0!

First number: q
  1. 处理FileNotFoundError 异常
  1. 分析文本
  1. 使用多个文件

try-except 代码块提供了两个重要的优点:

  1. 失败时一声不吭

passcontinuebreakexit()的区别:

  1. 决定报告哪些错误

4. 存储数据

  1. 使用json.dump() 和json.load()
import json
numbers = [2, 3, 5, 7, 11, 13]
filename = 'numbers.json'
with open(filename, 'w') as f_obj:#写入模式打开文件
    json.dump(numbers, f_obj)

json.load:

import json
filename = 'numbers.json'
with open(filename) as f_obj: 
    numbers = json.load(f_obj)
print(numbers)
  1. 保存和读取用户生成的数据
import json
# 如果以前存储了用户名,就加载它
# 否则,就提示用户输入用户名并存储它 
filename = 'username.json'
try:
    with open(filename) as f_obj: username = json.load(f_obj)
except FileNotFoundError:
    username = input("What is your name? ") 
    with open(filename, 'w') as f_obj:
        json.dump(username, f_obj)#保存用户输入
        print("We'll remember you when you come back, " + username + "!")
else:
    print("Welcome back, " + username + "!")

输出:

(base) Johnson-MacBook-Pro:python_work ligao$ python Chapter10_jasonloadtest.py 
What is your name? Eric
We'll remember you when you come back, Eric!
(base) Johnson-MacBook-Pro:python_work ligao$ python Chapter10_jasonloadtest.py 
Welcome back, Eric!
  1. 重构
    经常有这样的情况:
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:
        print("Welcome back, " + username + "!") 
    else:
        username = get_new_username()
        print("We'll remember you when you come back, " + username + "!")
greet_user()

None

is 和 ==

Chapter11 测试代码

1. 测试函数

  1. 单元测试和测试用例(TestCase())
  1. 可通过的测试
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase): 
    """测试name_function.py"""
    def test_first_last_name(self): 
        """能够正确地处理像Janis Joplin这样的姓名吗?"""
        formatted_name = get_formatted_name('janis', 'joplin') 
        self.assertEqual(formatted_name, 'Janis Joplin')
        
unittest.main()

输出:

.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
  1. 不能通过的测试
    例:
def get_formatted_name(first, middle, last): 
    """生成整洁的姓名"""
    full_name = first + ' ' + middle + ' ' + last 
    return full_name.title()

import unittest
#from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase): 
    """测试name_function.py"""
    def test_first_last_name(self): 
        """能够正确地处理像Janis Joplin这样的姓名吗?"""
        formatted_name = get_formatted_name('janis', 'joplin') 
        self.assertEqual(formatted_name, 'Janis Joplin')
        
unittest.main()

输出:

E
======================================================================
ERROR: test_first_last_name (__main__.NamesTestCase)
\u80fd\u591f\u6b63\u786e\u5730\u5904\u7406\u50cfJanis Joplin\u8fd9\u6837\u7684\u59d3\u540d\u5417?
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/ligao/Desktop/python_work/test_name_function.py", line 19, in test_first_last_name
    formatted_name = get_formatted_name('janis', 'joplin')
TypeError: get_formatted_name() missing 1 required positional argument: 'last'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

阅读输出的方式:

  1. 测试为通过时怎么办
def get_formatted_name(first, last, middle=''): 
    """生成整洁的姓名"""
    if middle:
        full_name = first + ' ' + middle + ' ' + last 
    else:
        full_name = first + ' ' + last 
    return full_name.title()
  1. 添加新测试
def test_first_last_middle_name(self): 
        """能够正确地处理像Wolfgang Amadeus Mozart这样的姓名吗?"""
        formatted_name = get_formatted_name( 'wolfgang', 'mozart', 'amadeus')
        self.assertEqual(formatted_name, 'Wolfgang Amadeus Mozart')

2. 测试类

  1. 各种断言方法

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 中
  1. 一个要测试的类
class AnonymousSurvey(): 
    """收集匿名调查问卷的答案"""
    def __init__(self, question): 
        """存储一个问题,并为存储答案做准备""" 
        self.question = question 
        self.responses = []
    def show_question(self): 
        """显示调查问卷""" 
        print(question)
    def store_response(self, new_response): 
        """存储单份调查答卷""" 
        self.responses.append(new_response)
    def show_results(self): 
        """显示收集到的所有答卷""" 
        print("Survey results:") 
        for response in responses:
            print('- ' + response)
  1. 测试AnonymousSurvey 类
import unittest
from survey import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase): 
    """针对AnonymousSurvey类的测试"""
    def test_store_single_response(self): 
        """测试单个答案会被妥善地存储""" 
        question = "What language did you first learn to speak?"
        my_survey = AnonymousSurvey(question) 
        my_survey.store_response('English')
        self.assertIn('English', my_survey.responses)
    
    def test_store_three_responses(self): 
        """测试三个答案会被妥善地存储"""
        question = "What language did you first learn to speak?" 
        my_survey = AnonymousSurvey(question)
        responses = ['English', 'Spanish', 'Mandarin'] 
        for response in responses:
            my_survey.store_response(response)
        for response in responses: 
            self.assertIn(response, my_survey.responses)

unittest.main()

输出结果:

..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK
  1. 方法setUp()
import unittest
from survey import AnonymousSurvey
class TestAnonymousSurvey(unittest.TestCase): 
    """针对AnonymousSurvey类的测试"""
    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_single_response(self): 
        """测试单个答案会被妥善地存储""" 
        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()

输出结果:

..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

测试用例输出的解读

运行测试用例时,每完成一个单元测试,Python都打印一个字符:
测试通过 -- 打印一个句点;
测试引发错误 -- 打印一个E ;
测试导致断言失败 -- 打印一个F

上一篇 下一篇

猜你喜欢

热点阅读