python学习之路 一:基础知识
本文最后更新于:2021年12月25日 下午
本文适合有基础c、c++语言知识的人学习,同时也可当作python工具书查阅。
前言
这里选择的是最新版 Python3
安装教程这里推荐:http://www.runoob.com/python3/python3-install.html
win下载地址:https://www.python.org/downloads/windows
Linux下载地址:https://www.python.org/downloads/source可视化开发工具IDE:https://www.jetbrains.com/pycharm/download/
因国内pip速度较慢,安装完python后建议改为国内清华大学镜像源,以下:
临时使用
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 模块名字
设为默认
升级 pip 到最新的版本 (>=10.0.0) 后进行配置:pip install pip -U
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
如果您到 pip 默认源的网络连接较差,临时使用本镜像站来升级 pip:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pip -U
指定目录 pip下载及离线安装包
- 将pip安装的包导出至requirements文件列表
cd进入想要下载的目录。pip freeze > requirements.txt
- 批量下载pip包
pip download -d d:\0\package -r requirements.txt
- pip批量安装包及通过列表文件安装(先cd进入requirements所在目录)
pip install -r requirements.txt
- 将pip安装的包导出至requirements文件列表
1.1基础语法
1.1.1 输出
打印 print ("Hello, Python!")
print 默认输出是换行的,如果要实现不换行需要在变量末尾加上逗号,
。
不换行输出 print('*', end=' ')
。
1 |
|
1.1.2 字符串转义
特殊字符会使用反斜杠\
来转义。比如\n
表示换行,\t
表示制表符,字符\
本身也要转义,所以\表示的字符就是\print('Isn\'t, they said.')
如果不希望前置了 \ 的字符转义成特殊字符,而是使用原始字符串方式,在引号前添加 r 即可。print(r'C:\软件\python')
用三重引号可以跨行连续输入。"""..."""
或'''...'''
字符串可以用 + 进行连接(粘到一起),也可以用 * 进行重复:3 * 'io' + ' so easy'
1.1.3 脚本式编程
Python 文件将以 .py
为扩展名。
在linux和mac上面编程时,已经设置了PATH变量,头文件加入#!/usr/bin/python
,可以直接执行。
1 |
|
这里,假定您的Python解释器在/usr/bin目录中,使用以下命令执行脚本:
1 |
|
1.1.4 行和缩进
Python与其他语言最大的区别就是,Python 的代码块不使用大括号 {} 来控制类,函数以及其他逻辑判断。python 最具特色的就是用缩进来写模块。
缩进的空白数量是可变的,但是所有代码块语句必须包含相同的缩进空白数量(一般是四个空格),这个必须严格执行。
1.1.5 注释
python中单行注释采用 # 开头。
python 中多行注释使用三个单引号(‘’’)或三个双引号(“””)。
1.1.6 同一行显示多条语句
Python可以在同一行中使用多条语句,语句之间使用分号(;)分割。
1.1.7 多个语句构成代码组
缩进相同的一组语句构成一个代码块,我们称之代码组。
像if、while、def和class这样的复合语句,首行以关键字开始,以冒号( : )结束,该行之后的一行或多行代码构成代码组。
我们将首行及后面的代码组称为一个子句(clause)。
如下实例:
1 |
|
1.2 变量类型
1.2.1 变量赋值
Python 中的变量赋值不需要类型声明。
Python允许你同时为多个变量赋值。例如:a, b, c = 1, 2, "john"
1.2.2 标准数据类型
Python 定义了一些标准类型,用于存储各种类型的数据。
Python有五个标准的数据类型:
- Numbers(数字)
- String(字符串)
- List(列表)
- Tuple(元组)
- Dictionary(字典)
bool类型有True和False和None(等于NULL)。
1.2.2.1 Python数字
数字数据类型用于存储数值。他们是不可改变的数据类型,这意味着改变数字数据类型会分配一个新的对象。
当你指定一个值时,Number对象就会被创建:var1 = 1
您也可以使用del语句删除一些对象的引用。del语句的语法是:del var1[,var2[,var3[....,varN]]]]
您可以通过使用del语句删除单个或多个对象的引用。例如:del var_a, var_b
Python支持四种不同的数字类型:
- int(有符号整型,如
0112L
,0xDEFL
,0x69
)# long 类型只在Python2.X版本中。在Python3.X版本中 long 类被 int 替代。 - float(浮点型,
-32.54e100
) - complex(复数,
4.53e-7j
)
1.2.2.2 Python字符串
字符串或串(String)是由数字、字母、下划线组成的一串字符。
python的字串列表有2种取值顺序:
- 从左到右索引默认0开始的,最大范围是字符串长度少1
- 从右到左索引默认-1开始的,最大范围是字符串开头
如果你要实现从字符串中获取一段子字符串的话,可以使用 [头下标:尾下标] 来截取相应的字符串,其中下标是从 0 开始算起,可以是正数或负数,下标可以为空表示取到头或尾。
[头下标:尾下标] 获取的子字符串包含头下标的字符,但不包含尾下标的字符。
1 |
|
字符串格式化
在 Python 中,字符串格式化使用与 C 中 sprintf 函数一样的语法。
1 |
|
1.2.2.3 Python列表
List(列表)相当于c语言中的数组。 是 Python 中使用最频繁的数据类型。
列表可以完成大多数集合类的数据结构实现。它支持字符,数字,字符串甚至可以包含列表(即嵌套)。
列表用 [ ]
标识,是 python 最通用的复合数据类型。
列表中值的切割也可以用到变量 [头下标:尾下标] ,就可以截取相应的列表,从左到右索引默认 0 开始,从右到左索引默认 -1 开始,下标可以为空表示取到头或尾。
加号 + 是列表连接运算符,星号 * 是重复操作。如下实例:
1 |
|
每当需要访问最后一个列表元素时,都可使用索引-1,来获取最后一个元素。如list[-1]
。squares = [value**2 for value in range(1,11)]
此列表解析生成1-10的平方数存入数组。list[1]=list[:]
可以复制列表。
1.2.2.4 Python 元组
元组是另一个数据类型,类似于 List(列表)。
元组用 () 标识。内部元素用逗号隔开。但是元组不能二次赋值,相当于只读列表。
元组是不允许更新的。而列表是允许更新的。
1.2.2.5 Python 字典
字典(dictionary)是除列表以外python之中最灵活的内置数据结构类型。列表是有序的对象集合,字典是无序的对象集合。
两者之间的区别在于:字典当中的元素是通过键来存取的,而不是通过偏移存取。
字典用”{ }”标识。字典由索引(key)和它对应的值value组成。
1 |
|
修改字典中的值
dict['color'] = 'yellow'
删除键-值对
del dict['color']
# 删除键’color’dict.clear()
# 清空字典del dict
# 删除字典遍历字典
1
2
3for key, value in dict.items():
print("\nKey: " + key)
print("Value: " + value)
1.2.3 Python数据类型转换
和c语言一样。当我们需要对数据内置的类型进行转换,数据类型的转换,你只需要将数据类型作为函数名即可。float(2)
1.2.4 如何查看模块及其方法的使用和它们的源码
- 进入cmd或者终端,python交互模式。
import 模块名
# 导入模块dir(模块名)
# 查看模块拥有的方法help(模块名)
# 查看模块介绍及其所含方法、拉到最后file后面查看源码路径help(方法名)
# 查看方法的内置帮助、用法
1.3 运算符
+、-、*、/、%
和c语言一样**
是幂,2**3=8
//
是取整除,9//2=4
比较运算符和c语言一样
赋值运算符和c语言一样,多了**=
,//=
位运算符和c语言一样
逻辑运算符:and
等同于c语言中的&&
,or
等于c语言中的||
,not
等于c语言中的!
1.3.1 成员运算符
除了以上的一些运算符之外,Python还支持成员运算符,测试实例中包含了一系列的成员,包括字符串,列表或元组。
- in
如果在指定的序列中找到值返回 True,否则返回 False。例子:x in y , 如果 x 在 y 序列中返回 True。 - not in
如果在指定的序列中没有找到值返回 True,否则返回 False。例子:x not in y , 如果 x 不在 y 序列中返回 True。
1.3.2 身份运算符
身份运算符用于比较两个对象的存储单元.
- is
is 是判断两个标识符是不是引用自一个对象。例子:x is y, 类似 id(x) == id(y) - is not
is not 是判断两个标识符是不是引用自不同对象。例子:x is not y , 类似 id(a) != id(b)
1.4 条件语句
if
等用于c语言中if
,else
等同于c语言中else
,elif
等同于c语言中else if
Python程序语言指定任何非0和非空(null)值为True,0 或者 null为False。
Python 编程中 if 语句用于控制程序的执行,基本形式为:
1 |
|
1.5 循环语句
有while,for循环,循环控制语句有break,continue,pass。
1.5.1 while
while 语句用于循环执行程序,即在某条件下,循环执行某段程序,以处理需要重复处理的相同任务。其基本形式为:
1 |
|
例子:
1 |
|
1.5.2 for
for循环的语法格式如下:
1 |
|
1 |
|
1 |
|
1.5.3 循环控制语句
break,continue和c语言相同。pass就是一个空语句,不做任何事情,一般用做占位语句。。
1.6 函数
Python内置了很多有用的函数,我们可以直接调用。可以直接从Python的官方网站查看文档:
Python的官方网站查看内置函数
比如求绝对值的函数abs,只有一个参数。
也可以在交互式命令行通过help(abs)查看abs函数的帮助信息。
1.6.1 定义函数
你可以定义一个由自己想要功能的函数,以下是简单的规则:
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
- 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
一般格式如下:
1 |
|
python函数的使用方法基本上和c语言相同,不用指定返回类型,可以返回列表,字典等。
一、python可以给函数指定默认值。def student(name='Li Ming', age=18):
如果函数有一个实参默认值为空,则必须确保为空的实参在最后一个。如:def get_name(first_name, last_name, middle_name=''):
二、将列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永久性的,这让你能够高效地处理大量的数据。
有时候,需要禁止函数修改列表。这时候,可向函数传递列表的副本而不是原件。def stu(name[:], age[:])
三、Python允许函数从调用语句中收集任意数量的实参。def make_pizza(*toppings):
形参名 *toppings 中的星号让Python创建一个名为 toppings 的空元组,并将收到的所有值都封装到这个元组中。
如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后。Python先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中。def make_pizza(size, *toppings):
四、使用任意数量的关键字实参def build_profile(first, last, **user_info):
1.6.2 将函数存储在模块中
可以将函数存储在被称为模块的独立文件中,再将模块导入到主程序中。跟c语言差不多,c语言中用头文件,函数文件。
- 导入整个模块
假设xxx.py
所在目录内有另外一个pizza.py
,添加import pizza
语句
导入名为模块 module_name.py 的的整个模块通用语法:import module_name
可使用下面的语法来使用其中任何一个函数:module_name.function_name ()
- 导入特定的函数
from module_name import function_0 , function_1 , function_2
通过用逗号分隔函数名,可根据需要从模块中导入任意数量的函数。
若使用这种语法,调用函数时就无需使用句点。make_pizza(16, 'pepperoni')
- 使用 as 给函数指定别名
指定别名的通用语法如下:from module_name import function_name as fn
- 使用 as 给模块指定别名
给模块指定别名的通用语法如下:import module_name as mn
- 导入模块中的所有函数
最好只导入你需要用的函数,或者导入整个模块并使用句点表示法。
导入模块 module_name 中的所有函数通用语法如下:from module_name import *
所有的 import 语句都应放在文件开头,唯一例外的情形是,在文件开头使用了注释来描述整个程序。
1.7 类
1.7.1 创建类
根据约定,在Python中,首字母大写的名称指的是类。
1 |
|
一 方法 init()
可参考c++中的构造函数。
- 我们将方法 init() 定义成了包含三个形参: self 、 name 和 age 。在这个方法的定义中,形参 self 必不可少,还必须位于其他形参的前面,相当于c++中的This指针。
- 因为Python调用这个 init() 方法来创建 Dog 实例时,将自动传入实参 self 。每个与类相关联的方法调用都自动传递实参 self ,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
- 我们将通过实参向 Dog() 传递名字和年龄; self 会自动传递,因此我们不需要传递它。每当我们根据 Dog 类创建实例时,都只需给最后两个形参( name 和 age )提供值。
- Dog 类还定义了另外两个方法: sit() 和 roll_over() 。由于这些方法不需要额外的信息,如名字,因此它们只有一个形参 self 。
二 根据类创建实例
- 访问属性
要访问实例的属性,可使用句点表示法。my_dog.name
- 调用方法
用句点表示法来调用 Dog 类中定义的任何方法。my_dog.roll_over()
- 给属性指定默认值
可以在方法 init()中添加默认值
如果你对某个属性这样做了,就无需包含为它提供初始值的形参。
三 修改属性的值
- 直接修改属性的值
my_dog.son='kuku'
- 通过方法修改属性的值
等于在类里面新建一个方法,来修改类里面属性的值def update_name(self, mile):
self.name = mile
- 通过方法对属性的值进行递增
跟2差不多,用方法里面的实参来修改。
1.7.2 继承
1 |
|
一 给子类定义属性和方法
super() 是一个特殊函数,帮助Python将父类和子类关联起来。这行代码让Python调用ElectricCar 的父类的方法 init() ,让 ElectricCar 实例包含父类的所有属性。父类也称为超类(superclass),名称super因此而得名。
二 重写父类的方法
可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。
1.7.3 导入类
Python允许你将类存储在模块中,然后在主程序中导入所需的模块。
- 导入类
from car import Car
- 从一个模块中导入多个类
from car import Car, ElectricCar
- 导入整个模块
你还可以导入整个模块,再使用句点表示法访问需要的类。import car
- 导入模块中的所有类
from module_name import *
#不推荐这种方式 - 在一个模块中导入另一个模块
1.7.4 类编码风格
类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。
1.8 文件和异常
1.8.1 从文件中读取数据
1.8.1.1 读取整个文件
open() 函数常用形式是接收两个参数:文件名(file)和模式(mode)。open(file, mode='r')
完整的语法格式为:open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
参数说明:
- file: 必需,文件路径(相对或者绝对路径)。
- mode: 可选,文件打开模式
- buffering: 设置缓冲
- encoding: 一般使用utf8
- errors: 报错级别
- newline: 区分换行符
- closefd: 传入的file参数类型
- opener:
1 |
|
函数 open() 接受一个参数:要打开的文件的名称。 函数 open()返回一个表示文件的对象。Python将这个对象存储在我们将在后面使用的变量中。
关键字 ==with== 在不再需要访问文件后将其关闭。在这个程序中,我们没有调用 close() ;你只管打开文件,并在需要时使用它,Python自会在合适的时候自动将其关闭。
有了表示 pi_digits.txt 的文件对象后,我们使用方法 read() (前述程序的第2行)读取这个文件的全部内容,并将其作为一个长长的字符串存储在变量 contents 中。这样,通过打印 contents 的值,就可将这个文本文件的全部内容显示出来。
相比于原始文件,该输出唯一不同的地方是末尾多了一个空行。为何会多出这个空行呢?因为 read() 到达文件末尾时返回一个空字符串,而将这个空字符串显示出来时就是一个空行。要删除多出来的空行,可在 print 语句中使用 rstrip() :print(contents.rstrip())
1.8.1.2 文件路径
在Linux和OS X中,你可以这样编写代码:file_path = '/home/ehmatthes/other_files/text_files/filename.txt'
with open(file_path) as file_object:
Windows系统中,在文件路径中使用反斜杠( \ )而不是斜杠( / ):file_path = 'C:\Users\ehmatthes\other_files\text_files\filename.txt'
with open(file_path) as file_object:
1.8.1.3 逐行读取
1 |
|
1.8.1.4 创建一个包含文件各行内容的列表
1 |
|
1.8.1.5 使用文件的内容
1 |
|
输出3.141592653589793238462643383279
在变量 pi_string 存储的字符串中,包含原来位于每行左边的空格,为删除这些空格,可使用 strip() 函数消除空格。print str.strip( '0' ); # 去除首尾字符 0
1.8.2 写入文件
1.8.2.1 写入空文件
1 |
|
打开文件时,可指定读取模式( ‘r’ )、写入模式( ‘w’ )、附加模式( ‘a’ )或让你能够读取和写入文件的模式( ‘r+’ )。如果
你省略了模式实参,Python将以默认的只读模式打开文件。
Python只能将字符串写入文本文件。要将数值数据存储到文本文件中,必须先使用函数str() 将其转换为字符串格式。
1.8.2.2 写入多行
每句后面加上换行符。
1.8.3 异常
Python使用被称为异常的特殊对象来管理程序执行期间发生的错误。每当发生错误时,它都会创建一个异常对象。如果你编写了处理该异常的代码,程序将继续运行;如果你未对异常进行处理,程序将停止,并显示一个traceback,其中包含有关异常的报告。
异常是使用 try-except 代码块处理的。 try-except 代码块让Python执行指定的操作,同时告诉Python发生异常时怎么办。使用了 try-except 代码块时,即便出现异常,程序也将继续运行:显示你编写的友好的错误消息,而不是令用户迷惑的traceback。
1.8.3.1 使用 try-except-else 代码块
1 |
|
当你认为可能发生了错误时,可编写一个 try-except
代码块来处理可能引发的异常。
通过将可能引发错误的代码放在 try-except
代码块中,可提高这个程序抵御错误的能力。这个示例还包含一个 else
代码块;依赖于 try
代码块成功执行的代码都应放到 else
代码块中。try-except-else
代码块的工作原理大致如下:Python尝试执行 try 代码块中的代码;只有可能引发异常的代码才需要放在 try 语句中。有时候,有一些仅在 try 代码块成功执行时才需要运行的代码;这些代码应放在 else 代码块中。 except 代码块告诉Python,如果它尝试运行 try 代码块中的代码时引发了指定的异常,该怎么办。
1.8.3.2 如何捕获异常
异常的类型太多,是否有方法捕获所有异常呢?
1 |
|
但是使用这样的方式,我们只知道是报了某个错误,不知道是哪个文件哪个函数的哪一行错误。我们可以使用traceback
获取详细的异常信息:
1 |
|
这样就比较直观,方便我们调试和修复代码。
1.8.3.3 分析多个文本
1 |
|
如果你希望失败的时候不提示用户,可以在 except xxxError 后面添加一句pass。
1.8.4 存储数据
模块 json 让你能够将简单的Python数据结构转储到文件中,并在程序再次运行时加载该文件中的数据。还可以使用 json 在Python程序之间分享数据。更重要的是,JSON数据格式并非Python专用的,这让你能够将以JSON格式存储的数据与使用其他编程语言的人分享。
1.8.4.1 使用 json.dump() 和 json.load() 保存和读取用户生成的数据
1 |
|
先导入模块json,通过方法json.dump() 和 json.load()来保存用户名。
上面的程序,如果第一次执行,保存用户名到username,第二次执行则显示欢迎回来。
1.8.4.2 重构
有时候,我们要保证高内聚,低耦合,需要将各个模块代码分为一系列完成具体工作的函数,这样的过程称为重构。
下面我们来重构上一节的代码:
1 |
|
在这个最终版本中,每个函数都执行单一而清晰的任务。要编写出清晰而易于维护和扩展的代码,划分工作必不可少。
1.9 测试代码
这章中我们学习如何使用Python模块 unittest 中的工具来测试代码。
1.9.1 测试函数
1.9.1.1 单元测试和测试用例
Python标准库中的模块 unittest 提供了代码测试工具。单元测试用于核实函数的某个方面没有问题;测试用例是一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求。良好的测试用例考虑到了函数可能收到的各种输入,包含针对所有这些情形的测试。全覆盖式测试用例包含一整套单元测试,涵盖了各种可能的函数使用方式。对于大型项目,要实现全覆盖可能很难。通常,最初只要针对代码的重要行为编写测试即可,等项目被广泛使用时再考虑全覆盖。
1.9.1.2 如何测试
要为函数编写测试用例,可先导入模块 unittest 以及要测试的函数,再创建一个继承 unittest.TestCase 的类,并编写一系列方法对函数行为的不同方面进行测试。
下面是一个只包含一个方法的测试用例,它检查函数 get_formatted_name() 在给定名和姓时能否正确地工作:
1 |
|
1 |
|
首先,我们导入了模块 unittest 和要测试的函数 get_formatted_ name() 。我们创建了一个名为 NamesTestCase(名字随便) 的类,用于包含一系列针对 get_formatted_name() 的单元测试。这个类必须继承unittest.TestCase 类,这样Python才知道如何运行你编写的测试。
我们运行 test_name_function.py 时,所有以 test_ 打头的方法都将自动运行。
在这个方法中,我们调用了要测试的函数,并存储了要测试的返回值。
最后我们使用了 unittest 类最有用的功能之一:一个断言方法。断言方法用来核实得到的结果是否与期望的结果一致。
我们调用 unittest 的方法 assertEqual() ,并向它传递 formatted_name 和 ‘Janis Joplin’ 。代码行 self.assertEqual(formatted_name, 'Janis Joplin')
的意思是说:“将 formatted_name 的值同字符串 ‘Janis Joplin’ 进行比较,如果它们相等,就万事大吉,如果它们不相等,跟我说一声!”
1.9.2 测试类
1.9.2.1 各种断言方法
Python在 unittest.TestCase 类中提供了很多断言方法。如下:
方 法 | 用 途 |
---|---|
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.9.2.2 方法 setUp()
1 |
|
1 |
|
使用 setUp() 来创建一个调查对象和一组答案,供方法 test_store_single_response()
和 test_store_three_responses()
使用。
方法 setUp() 做了两件事情:创建一个调查对象(见方法setUp()第4行);创建一个答案列表(见方法setUp()第5行)。
这让两个测试方法都更简单,因为它们都不用创建调查对象和答案。方法 test_store_three_response()
核实 self.responses 中的第一个答案—— self.responses[0] ——被妥善地存储,而方法 test_store_three_response()
核实 self.responses 中的全部三个答案都被妥善地存储。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!