Python编程从入门到实践-读书笔记

473 阅读27分钟

本书作为一本非常适合入门的书籍,对于我这种有编程经验的人来说,读起来确实比较轻松。主要分为两部书:基础知识和项目。

基础知识重点摘录

字符串

在Python中,用引号括起的都是字符串,其中的引号可以是单引号,也可以是双引号。这种灵活性让你能够在字符串中包含引号和撇号:

  • 'I told my friend, "Python is my favorite language!"'
  • "The language 'Python' is named after Monty Python, not the snake."
  • "One of Python's strengths is its diverse and supportive community."

在用单引号括起的字符串中,如果包含撇号,就将导致错误。这是因为这会导致Python将第一个单引号和撇号之间的内容视为一个字符串,进而将余下的文本视为Python代码,从而引发错误。

数字

Python使用两个乘号表示乘方运算。

空格不影响Python计算表达式的方式,它们的存在旨在让你阅读代码时,能迅速确定先执行哪些运算。如: 2 + 3*4(2 + 3) * 4

列表

  • 在Python中,用方括号([])来表示列表,并用逗号来分隔其中的元素。
  • Python为访问最后一个列表元素提供了一种特殊语法。通过将索引指定为-1,这种约定也适用于其他负数索引,例如,索引-2返回倒数第二个列表元素。
  • 修改列表元素:motorcycles[0] = 'ducati'
  • 在列表中添加元素:
    • 在列表末尾添加元素motorcycles.append('ducati')
    • 在列表中插入元素:motorcycles.insert(0, 'ducati')
  • 从列表中删除元素:
    • 使用del语句删除元素:del motorcycles[1]
    • 使用方法pop()删除元素(将元素从列表中删除,并接着使用它的值): motorcycles.pop(5)
  • 根据值删除元素:motorcycles.remove('ducati'),方法remove()只删除第一个指定的值。如果要删除的值可能在列表中出现多次,就需要使用循环来判断是否删除了所有这样的值。
  • 排序
    • 使用方法 sort() 对列表进行永久性排序
    • 使用函数 sorted() 对列表进行临时排序,如果你要按与字母顺序相反的顺序显示列表,也可向函数sorted()传递参数reverse=True
  • 确定列表的长度:len(cars)
  • 使用 range()创建数字列表,还可指定步长:list(range(2,11,2))
  • 列表解析:squares = [value**2 for value in range(1,11)]
  • 复制列表:使用friend_foods = my_foods[:];而不是friend_foods = my_foods,使用赋值不能得到两个列表。

元组

  • 列表是可以修改的,Python将不能修改的值称为不可变的,而不可变的列表被称为元组。
  • 元组看起来犹如列表,但使用圆括号而不是方括号来标识。定义元组后,就可以使用索引来访问其元素,就像访问列表元素一样。
  • 虽然不能修改元组的元素,但可以给存储元组的变量赋值

字典

在Python中, 字典是一系列键—值对。每个键都与一个值相关联,你可以使用键来访问与之相关联的值。与键相关联的值可以是数字、字符串、列表乃至字典。事实上,可将任何Python对象用作字典中的值。

使用字典来存储用户提供的数据或在编写能自动生成大量键—值对的代码时,通常都需要先定义一个空字典。

  • 访问字典中的值:print(alien_0['color'])
  • 添加键—值对:alien_0['x_position'] = 0
  • 修改字典中的值:alien_0['color'] = 'yellow'
  • 删除键—值对:del alien_0['points']
  • 遍历所有的键—值对:for key, value in user_0.items():
  • 遍历字典中的所有键:for name in favorite_languages.keys():
  • 按顺序遍历字典中的所有键:for name in sorted(favorite_languages.keys()):
  • 遍历字典中的所有值:for language in favorite_languages.values():,这种做法提取字典中所有的值,而没有考虑是否重复。如果需要踢出重复项,使用for language in set(favorite_languages.values()):

嵌套

  • 在列表中嵌套字典
  • 在字典中嵌套列表
  • 在字典中嵌套字典

注意:列表和字典的嵌套层级不应太多。

用户输入

  • 函数input()让程序暂停运行,等待用户输入一些文本。例如:message = input("Tell me something, and I will repeat it back to you: ")
  • 使用函数input()时, Python将用户输入解读为字符串。而函数int()将数字的字符串表示转换为数值表示,如:age = int(age)

for 与 while 循环

  • for循环是一种遍历列表的有效方式,但在for循环中不应修改列表,否则将导致Python难以跟踪其中的元素。
  • 要在遍历列表的同时对其进行修改,可使用while循环。通过将while循环同列表和字典结合起来使用,可收集、存储并组织大量输入,供以后查看和显示。

函数

  • 传递实参:
    • 位置实参,这要求实参的顺序与形参的顺序相同,如:describe_pet('harry', 'hamster')
    • 关键字实参,其中每个实参都由变量名和值组成;还可使用列表和字典,如:describe_pet(animal_type='hamster', pet_name='harry')注意:使用关键字实参时,务必准确地指定函数定义中的形参名。
  • 默认值:编写函数时,可给每个形参指定默认值。给形参指定默认值后,可在函数调用中省略相应的实参。使用默认值可简化函数调用,还可清楚地指出函数的典型用法。注意 使用默认值时,在形参列表中必须先列出没有默认值的形参,再列出有默认值的实参。这让Python依然能够正确地解读位置实参。
  • 可混合使用位置实参、关键字实参和默认值,通常有多种等效的函数调用方式。使用哪种调用方式无关紧要,只要函数调用能生成你希望的输出就行。使用对你来说最容易理解的调用方式即可
  • 传递列表
    • 在函数中修改列表:在函数中对这个列表所做的任何修改都是永久性的,这让你能够高效地处理大量的数据。
    • 禁止函数修改列表:切片表示法[:]创建列表的副本。
    • 虽然向函数传递列表的副本可保留原始列表的内容,但除非有充分的理由需要传递副本,否则还是应该将原始列表传递给函数,因为让函数使用现成列表可避免花时间和内存创建副本,从而提高效率,在处理大型列表时尤其如此。
  • 传递任意数量的实参:形参名*toppings中的星号让Python创建一个名为toppings的空元组,并将收到的所有值都封装到这个元组中。如:def make_pizza(*toppings):
  • 结合使用位置实参和任意数量实参:如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后。 如:def make_pizza(size, *toppings):
  • 使用任意数量的关键字实参:预先不知道传递给函数的会是什么样的信息。在这种情况下,可将函数编写成能够接受任意数量的键—值对。如:def build_profile(first, last, **user_info):
  • 编写函数时,你可以以各种方式混合使用位置实参、关键字实参和任意数量的实参。知道这些实参类型大有裨益,因为阅读别人编写的代码时经常会见到它们。

导入函数(将函数存储在模块)

函数的优点之一是,使用它们可将代码块与主程序分离。通过给函数指定描述性名称,可让主程序容易理解得多。你还可以更进一步,将函数存储在被称为模块的独立文件中,再将模块导入到主程序中。

  • 导入整个模块:import module_name

  • 导入特定的函数:from module_name import function_name

  • 使用 as 给函数指定别名:from module_name import function_name as fn

  • 使用 as 给模块指定别名:import module_name as mn

  • 导入模块中的所有函数:from module_name import *,使用并非自己编写的大型模块时,最好不要采用这种导入方法(如果模块中有函数的名称与你的项目中使用的名称相同,可能导致意想不到的结果),最佳的做法是,要么只导入你需要使用的函数,要么导入整个模块并使用句点表示法。这能让代码更清晰,更容易阅读和理解。

class Car():
    """一次模拟汽车的简单尝试"""
    
    def __init__(self, make, model, year):
        """初始化描述汽车的属性"""
        self.make = make
        self.model = model
        self.year = year
    
    def get_descriptive_name(self):
        """返回整洁的描述性信息"""
        long_name = str(self.year) + ' ' + self.make + ' ' + self.model
        return long_name.title()
  • 每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
  • 根据约定,在Python中,我们通常可以认为首字母大写的名称(如:Dog)指的是类,而小写的名称(如my_dog)指的是根据类创建的实例。如:my_dog = Dog('willie', 6)
  • 句点表示法:
    • 访问实例的属性:my_dog.name
    • 调用Dog类中定义的任何方法:my_dog.sit()

类继承

一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类,而新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。

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

导入类(将类存储在模块)

为遵循Python的总体理念,应让文件尽可能整洁。为在这方面提供帮助, Python允许你将类存储在模块中,然后在主程序中导入所需的模块。

  • 导入单个类:from car import ElectricCar
  • 从一个模块中导入多个类: from car import Car, ElectricCar
  • 导入整个模块:import car,然后使用语法module_name.class_name访问需要的类。
  • 导入模块中的所有类。如:from module_name import *,不推荐使用这种导入方式。
  • 需要从一个模块中导入很多类时,最好导入整个模块,并使用module_name.class_name语法来访问类。这样做时,虽然文件开头并没有列出用到的所有类,但你清楚地知道在程序的哪些地方使用了导入的模块;你还避免了导入模块中的每个类可能引发的名称冲突。

文件

读取文件

with open('pi_digits.txt') as file_object:
    contents = file_object.read()
    print(contents)
  • 要以任何方式使用文件——哪怕仅仅是打印其内容,都得先打开文件,这样才能访问它。
  • 关键字with在不再需要访问文件后将其关闭。
  • 逐行读取:for line in file_object:
  • 使用关键字with时, open()返回的文件对象只在with代码块内可用。如果要在with代码块外访问文件的内容,可在with代码块内将文件的各行存储在一个列表中,并在with代码块外使用该列表,创建一个包含文件各行内容的列表:lines = file_object.readlines()
  • 读取文本文件时, Python将其中的所有文本都解读为字符串。如果你读取的是数字,并要将其作为数值使用,就必须使用函数int()将其转换为整数,或使用函数float()将其转换为浮点数。

写入文件

filename = 'programming.txt'
    with open(filename, 'w') as file_object:
    file_object.write("I love programming.")
  • 打开文件时,可指定读取模式( 'r')、 写入模式( 'w')、 附加模式( 'a')或让你能够读取和写入文件的模式( 'r+')。如果你省略了模式实参, Python将以默认的只读模式打开文件
  • 如果你要写入的文件不存在,函数open()将自动创建它。
  • 以写入( 'w')模式打开文件时千万要小心,因为如果指定的文件已经存在,Python将在返回文件对象前清空该文件。
  • Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数str()将其转换为字符串格式。

使用Json格式存取数据

  • 存储数据:json.dump(numbers, f_obj),其中,f_obj为文件对象。
  • 读取数据:numbers = json.load(f_obj),其中,f_obj为文件对象。

异常

Python使用被称为异常的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知所措的错误时,它都会创建一个异常对象。

  • 如果你编写了处理该异常的代码,程序将继续运行;
  • 如果你未对异常进行处理,程序将停止,并显示一个traceback,其中包含有关异常的报告。

异常是使用try-except代码块处理的。使用了try-except代码块时,即便出现异常,程序也将继续运行:显示你编写的友好的错误消息,而不是令用户迷惑的traceback。

示例:

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: ")
    try:
        answer = int(first_number) / int(second_number)
    except ZeroDivisionError:
        print("You can't divide by 0!")
    else:
        print(answer)

有一些仅在try代码块成功执行时才需要运行的代码;这些代码应放在else代码块中。 except代码块告诉Python,如果它尝试运行try代码块中的代码时引发了指定的异常,该怎么办。

通过预测可能发生错误的代码,可编写健壮的程序,它们即便面临无效数据或缺少资源,也能继续运行,从而能够抵御无意的用户错误和恶意的攻击。

测试代码

单元测试和测试用例

Python标准库中的模块unittest提供了代码测试工具。

  • 单元测试用于核实函数的某个方面没有问题;
  • 测试用例是一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求。
  • 全覆盖式测试用例包含一整套单元测试,涵盖了各种可能的函数使用方式。对于大型项目,要实现全覆盖可能很难。通常,最初只要针对代码的重要行为编写测试即可。

测试未通过时怎么办?

测试未通过时,不要修改测试,而应修复导致测试不能通过的代码:检查刚对函数所做的修改,找出导致函数行为不符合预期的修改。

各种断言方法

unittest Module中的断言方法如下:

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

针对方法进行测试

针对方法进行测试得示例如下:

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')
    
    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')
    unittest.main()

在TestCase类中使用很长的方法名是可以的;这些方法的名称必须是描述性的,这才 能让你明白测试未通过时的输出。

针对类进行测试

针对类进行测试得示例如下:

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()

测试自己编写的类时,方法setUp()让测试方法编写起来更容易:可在setUp()方法中创建一系列实例并设置它们的属性,再在测试方法中直接使用这些实例。

注意:运行测试用例时,每完成一个单元测试, Python都打印一个字符:测试通过时打印一个句点;测试引发错误时打印一个E;测试导致断言失败时打印一个F。这就是你运行测试用例时,在输出的第一行中看到的句点和字符数量各不相同的原因。如果测试用例包含很多单元测试,需要运行很长时间,就可通过观察这些结果来获悉有多少个测试通过了。

设置代码格式

代码被阅读的次数比编写的次数多。如果一定要在让代码易于编写和易于阅读之间做出选择, Python程序员几乎总是会选择后者。

  • 缩进:PEP 8建议每级缩进都使用四个空格,这既可提高可读性,又留下了足够的多级缩进空间。混合使用制表符和空格会让Python解释器感到迷惑。在程序中混合使用制表符和空格可能导致极难解决的问题。
  • 行长:很多Python程序员都建议每行不超过80字符。PEP 8还建议注释的行长都不超过72字符,因为有些工具为大型项目自动生成文档时,会在每行释开头添加格式化字符。
  • 空行:你应该使用空行来组织程序文件,但也不能滥用。空行不会影响代码的运行,但会影响代码的可读性。 Python解释器根据水平缩进情况来解读代码,但不关心垂直间距。
  • 在条件测试的格式设置方面, PEP 8提供的唯一建议是,在诸如==、 >=和<=等比较运算符两边各添加一个空格,例如, if age < 4:要比if age<4:好。

变量的规则

  • 变量名只能包含字母、数字和下划线。变量名可以字母或下划线打头,但不能以数字打头,例如,可将变量命名为message_1,但不能将其命名为1_message。
  • 变量名不能包含空格,但可使用下划线来分隔其中的单词。例如,变量名greeting_message可行,但变量名greeting message会引发错误。
  • 不要将Python关键字和函数名用作变量名,即不要使用Python保留用于特殊用途的单词,如print
  • 变量名应既简短又具有描述性。例如, name比n好, student_name比s_n好, name_length比length_of_persons_name好。
  • 慎用小写字母l和大写字母O,因为它们可能被人错看成数字1和0。

  要创建良好的变量名,需要经过一定的实践,在程序复杂而有趣时尤其如此。随着你编写的程序越来越多,并开始阅读别人编写的代码,将越来越善于创建有意义的变量名。

注意:就目前而言,应使用小写的Python变量名,避免使用大写字母。

该编写什么样的注释

  • 编写注释的主要目的是阐述代码要做什么,以及是如何做的。
  • 你总是可以通过研究代码来确定各个部分的工作原理,但通过编写注释,以清晰的自然语言对解决方案进行概述,可节省很多时间。
  • 编写有意义的注释。如果不确定是否要编写注释,就问问自己,找到合理的解决方案前,是否考虑了多个解决方案。如果答案是肯定的,就编写注释对你的解决方案进行说明吧。
  • 相比回过头去再添加注释,删除多余的注释要容易得多。

Python 之禅

过于强调灵活性会导致大型项目难以维护:要通过研究代码搞清楚当时解决复杂问题的人是怎么想的,既困难又麻烦,还会耗费大量的时间。经验丰富的程序员倡导尽可能避繁就简。 Python社区的理念都包含在Tim Peters撰写的“Python之禅”中。通过如下方式获取即可:

>>> import this

The Zen of Python, by Tim Peters

Beautiful is better than ugly. # 编程是要解决问题的,设计良好、高效而漂亮的解决方案都会让程序员心生敬意。

Simple is better than complex. # 如果有两个解决方案,一个简单,一个复杂,但都行之有效,就选择简单的解决方案吧。这样,你编写的代码将更容易维护,你或他人以后改进这些代码时也会更容易。

Complex is better than complicated. # 现实是复杂的,有时候可能没有简单的解决方案。在这种情况下,就选择最简单可行的解决方案。

Readability counts. # 即便是复杂的代码,也要让它易于理解。开发的项目涉及复杂代码时,一定要为这些代码编写有益的注释。

Now is better than never. # 不要企图编写完美无缺的代码;先编写行之有效的代码,再决定是对其做进一步改进,还是转而去编写新代码。

...

函数编写指南

  • 应给函数指定描述性名称,且只在其中使用小写字母和下划线。描述性名称可帮助你和别人明白代码想要做什么。给模块命名时也应遵循上述约定。

  • 每个函数都应包含简要地阐述其功能的注释,该注释应紧跟在函数定义后面,并采用文档字符串格式。文档良好的函数让其他程序员只需阅读文档字符串中的描述就能够使用它。

  • 形参指定默认值时,等号两边不要有空格:def function_name(parameter_0, parameter_1='default value')

  • 对于函数调用中的关键字实参,也应遵循这种约定:function_name(value_0, parameter_1='value')

  • 如果形参很多,导致函数定义的长度超过了79字符,可在函数定义中输入左括号后按回车键,并在下一行按两次Tab键,从而将形参列表和只缩进一层的函数体区分开来。

  • 所有的import语句都应放在文件开头,唯一例外的情形是,在文件开头使用了注释来描述整个程序。

类编码风格

  • 类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。
  • 对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种文档字符串简要地描述类的功能,并遵循编写函数的文档字符串时采用的格式约定。每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。
  • 可使用空行来组织代码,但不要滥用。在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。
  • 需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的import语句,再添加一个空行,然后编写导入你自己编写的模块的import语句。在包含多条import语句的程序中,这种做法让人更容易明白程序使用的各个模块都来自何方。

重构

将代码划分为一系列完成具体工作的函数。这样的过程被称为重构。重构让代码更清晰、更易于理解、更容易扩展。

项目部分重点摘录

游戏项目:外星人入侵

规划项目

开发大型项目时,做好规划后再动手编写项目很重要。规划可确保你不偏离轨道,从而提高项目成功的可能性。

依赖库:Pygame

在Pygame中,颜色是以RGB值指定的。这种颜色由红色、绿色和蓝色值组成,其中每个值的可能取值范围都为0~255。颜色值(255, 0, 0)表示红色, (0, 255, 0)表示绿色,而(0, 0, 255)表示蓝色。通过组合不同的RGB值,可创建1600万种颜色。

编写一个名为settings的模块,其中包含一个名为Settings的类,用于将所有设置存储在一个地方,以免在代码中到处添加设置。这样,我们就能传递一个设置对象,而不是众多不同的设置。

在大型项目中,经常需要在添加新代码前重构既有代码。重构旨在简化既有代码的结构,使其更容易扩展。

一开始将代码编写得尽可能简单,并在项目越来越复杂时进行重构。

研究既有代码,确定实现新功能前是否要进行重构。

数据可视化项目

依赖库:

  • matplotlib:它是一个数学绘图库,我们将使用它来制作简单的图表,如折线图和散点图。
  • Pygal:它专注于生成适合在数字设备上显示的图表。通过使用Pygal, 可在用户与图表交互时突出元素以及调整其大小,还可轻松地调整整个图表的尺寸,使其适合在微型智能手表或巨型显示器上显示。

matplotlib

  • 折线图plt.plot(input_values, squares, linewidth=5)
  • 散点图plt.scatter(x_values, y_values, s=100)
  • 使用颜色映射plt.scatter(x_values, y_values, c=y_values, cmap=plt.cm.Blues, edgecolor='none', s=40),颜色映射(colormap)是一系列颜色,它们从起始颜色渐变到结束颜色。
  • 自动保存图表plt.savefig('squares_plot.png', bbox_inches='tight'),其中:第二个实参指定将图表多余的空白区域裁剪掉。如果要保留图表周围多余的空白区域,可省略这个实参。
  • 隐藏坐标轴:plt.axes().get_xaxis().set_visible(False)
  • 设置绘图窗口的尺寸:plt.figure(dpi=128, figsize=(10, 6)),其中:形参figsize指定一个元组,向matplotlib指出绘图窗口的尺寸,单位为英寸。如果你知道自己的系统的分辨率,可使用形参dpi向figure()传递该分辨率,以有效地利用可用的屏幕空间。
  • 给图表区域着色plt.fill_between(dates, highs, lows, facecolor='blue', alpha=0.1)
  • 绘制斜的日期标签fig.autofmt_xdate(),以免它们彼此重叠。

pygal

使用 Python 可视化包Pygal来生成可缩放的矢量图形文件。

如果你打算以在线方式使用图表,请考虑使用Pygal来生成它们,这样它们在任何设备上显示时都会很美观。

  • 绘制直方图 hist = pygal.Bar()

Pygal使用的国别码存储在模块i18n(internationalization的缩写)中。字典COUNTRIES包含的键和值分别为两个字母的国别码和国家名。

Pygal提供了图表类型Worldmap,可帮助你制作呈现各国数据的世界地图。

datetime

字符串转日期对象示例:

from datetime import datetime

first_date = datetime.strptime('2014-7-1', '%Y-%m-%d')
print(first_date)

模块datetime中设置日期和时间格式的实参:

  • %A 星期的名称,如Monday
  • %B 月份名,如January
  • %m 用数字表示的月份( 01~12)
  • %d 用数字表示月份中的一天( 01~31)
  • %Y 四位的年份,如2015
  • %y 两位的年份,如15
  • %H 24小时制的小时数( 00~23)
  • %I 12小时制的小时数( 01~12)
  • %p am或pm
  • %M 分钟数( 00~59)
  • %S 秒数( 00~61)

两种常见格式存储的数据:CSV和JSON

读取 CSV 格式数据:

import csv

# 从文件中获取最高气温
filename = 'sitka_weather_07-2014.csv'
with open(filename) as f:
    reader = csv.reader(f)
    header_row = next(reader)
    
    highs = []
    for row in reader:
        highs.append(row[1])
        
    print(highs)

读取 JSON 格式数据:

import json

# 将数据加载到一个列表中
filename = 'population_data.json'
with open(filename) as f:
    pop_data = json.load(f)
    
# 打印每个国家2010年的人口数量
for pop_dict in pop_data:
    if pop_dict['Year'] == '2010':
        country_name = pop_dict['Country Name']
        population = int(float(pop_dict['Value']))
        print(country_name + ": " + population)

Python不能直接将包含小数点的字符串转换为整数,为消除这种错误,我们需要先将字符串转换为浮点数,再将浮点数转换为整数。

requests

接口请求示例:

import requests

# 执行API调用并存储响应
url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)
print("Status code:", r.status_code)

# 将API响应存储在一个变量中
response_dict = r.json()

# 处理结果
print(response_dict.keys())

WEB应用程序项目

制定规范

完整的规范详细说明了项目的目标,阐述了项目的功能,并讨论了项目的外观和用户界面。与任何良好的项目规划和商业计划书一样,规范应突出重点,帮助避免项目偏离轨道。

对网站管理员隐藏有些敏感信息。例如, Django并不存储你输入的密码,而存储从该密码派生出来的一个字符串——散列值。每当你输入密码时, Django都计算其散列值,并将结果与存储的散列值进行比较。如果这两个散列值相同,就通过了身份验证。通过存储散列值,即便黑客获得了网站数据库的访问权,也只能获取其中存储的散列值,而无法获得密码。在网站配置正确的情况下,几乎无法根据散列值推导出原始密码。

在大型项目中,通常有一个用于整个网站的父模板——base.html,且网站的每个主要部分都有一个父模板。每个部分的父模板都继承base.html,而网站的每个网页都继承相应部分的父模板。这让你能够轻松地修改整个网站的外观、网站任何一部分的外观以及任何一个网页的外观。这种配置提供了一种效率极高的工作方式,让你乐意不断地去改进网站。

Django根据settings.py中设置SECRET_KEY的值来实现大量的安全协议。在这个项目中,我们提交到仓库的设置文件包含设置SECRET_KEY。对于生产网站,应更细致地处理设置SECRET_KEY。如果你创建的项目的用途很重要,务必研究如何更安全地处理设置SECRET_KEY。

附录重点摘录-寻求帮助

每个人学习编程时都会遇到困难,因此作为程序员,需要学习的最重要的技能之一是如何高效地摆脱困境

第一步:判断形势。

明确回答三个问题

你必须能够明确地回答如下三个问题,才能够从他人那里获得帮助。

  1. 你想要做什么?(陈述足够详细,让Python社区的其他人员能够施以援手)
  2. 你已尝试哪些方式?(你的答案应提供足够多的细节,这样别人就不会建议你去重复已经尝试过的方式)
  3. 结果如何?(知道准确的错误消息对在线搜索解决方案或寻求帮助很有用)

有时候,通过回答这三个问题,你会发现遗漏了什么,从而无需再做其他的事情就能摆脱困境。

再试试

有时候,只需回过头去重新来一次,就足以解决很多问题。

歇一会儿

如果你很长时间内一直在试图解决同一个问题,那么休息一会儿实际上是你可采取的最佳战术。长时间从事一个任务时,你可能变得一根筋,脑子里想的都是一个解决方案。你对所做的假设往往会视而不见,而休息一会儿有助于你从不同的角度看问题。不用休息很长时间,只需让你能够摆脱当前的思维方式就行。如果你坐了很长时间,起来做做运动。溜达溜达或去外面待一会儿,也可以喝杯水,或者吃点清淡而健康的零食。

如果你心情沮丧,也许该将工作放到一边,整天都不考虑了。晚上睡个好觉后,你常常会发现问题并不是那么难解决。

第二步:在线搜索

良好的搜索技能和具体的关键字有助于你找到现有的资源,供你用来解决当前面临的问题。

搜索计算机显示的错误消息也极有帮助。

第三步:IRC

程序员可通过IRC( Internet Relay Chat)实时地交流。如果你被问题困住,那么在网上搜索也找不到答案,那么在相关的IRC频道( channel)中寻求帮助可能是最佳选择。出没在这些频道中的人大多彬彬有礼、乐于助人,在你能够详细地描述你想做什么、尝试了哪些方法以及这些方法的结果时尤其如此。

经验

  • 要理解新的编程概念,最佳的方式是尝试在程序中使用它们。
  • 作为新手,最值得养成的习惯之一是,在代码中编写清晰、简洁的注释。
  • 有时候,使用临时变量会让代码更易读;而在其他情况下,这样做只会让代码无谓地变长。你首先应该考虑的是,编写清晰易懂且能完成所需功能的代码;等到审核代码时,再考虑采用更高效的方法。
  • 一开始应让代码结构尽可能简单。先尽可能在一个文件中完成所有的工作,确定一切都能正确运行后,再将类移到独立的模块中。如果你喜欢模块和文件的交互方式,可在项目开始时就尝试将类存储到模块中。先找出让你能够编写出可行代码的方式,再尝试让代码更为组织有序。
  • 每个函数都执行单一而清晰的任务。