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

简介: 基础知识重点摘录字符串在Python中,用引号括起的都是字符串,其中的引号可以是单引号,也可以是双引号。这种灵活性让你能够在字符串中包含引号和撇号:

基础知识重点摘录


字符串

在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变量名,避免使用大写字母。

相关文章
|
1天前
|
SQL 关系型数据库 MySQL
第十三章 Python数据库编程
第十三章 Python数据库编程
|
1天前
|
Python
Python从入门到精通:深入学习面向对象编程——2.1.2继承、封装和多态的概念
Python从入门到精通:深入学习面向对象编程——2.1.2继承、封装和多态的概念
|
1天前
|
存储 索引 Python
Python从入门到精通——1.3.1练习编写简单程序
Python从入门到精通——1.3.1练习编写简单程序
|
1天前
|
开发框架 前端开发 数据库
Python从入门到精通:3.3.2 深入学习Python库和框架:Web开发框架的探索与实践
Python从入门到精通:3.3.2 深入学习Python库和框架:Web开发框架的探索与实践
|
1天前
|
数据采集 数据可视化 数据处理
Python从入门到精通的文章3.3.1 深入学习Python库和框架:数据处理与可视化的利器
Python从入门到精通的文章3.3.1 深入学习Python库和框架:数据处理与可视化的利器
|
1天前
|
Java 数据库连接 数据处理
Python从入门到精通:3.1.2多线程与多进程编程
Python从入门到精通:3.1.2多线程与多进程编程
|
1天前
|
存储 网络协议 关系型数据库
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
|
5天前
|
机器学习/深度学习 搜索推荐 Python
Python特征工程面试:从理论到实践
【4月更文挑战第17天】本文探讨了Python在数据科学面试中的特征工程,涵盖基础概念如特征选择和提取,实战技能如缺失值和异常值处理,以及特定场景应用。强调避免过度依赖单一方法,忽视数据分布和相关性,以及保持特征工程的可解释性。提供代码示例展示了处理缺失值、标准化、特征选择和异常值检测的基本操作。建议结合业务理解,灵活运用多种方法并注重模型解释性。
20 9
|
1月前
|
缓存 分布式计算 自然语言处理
Python语言的函数编程模块
Python语言的函数编程模块
|
2月前
|
安全 调度 Python
什么是Python中的事件驱动编程?如何使用`asyncio`模块实现异步事件处理?
【2月更文挑战第4天】【2月更文挑战第9篇】什么是Python中的事件驱动编程?如何使用`asyncio`模块实现异步事件处理?