Pascal之父,尼古拉斯·沃斯(Nicklaus Wirth)有这么一句名言:程序(Program)=算法(Algorithm)+数据结构(Data Structure)。依据该理论,本章将从“程序=数据+算法”的角度进行展开,其中数据分为数据结构和数据类型。结构决定功能,功能一般通过相关的算法(函数或方法)及其控制结构实现,如图2-1所示。
图2-1 程序的构成
Python是一门面向对象编程的语言,它具备丰富的库,能够轻松地与其他语言进行连接,因此Python语言也经常被称为“胶水”语言。在Python中,“类、成员、对象、属性、方法”是面向对象编程的几个核心概念。例如把具有相同属性和方法的对象归为一个类(class),“物以类聚”,类是抽象的。对象是某个类中的每个实体,对象是类的实例化结果,万物皆对象,对象是具体存在的事物。对象可以有自己的属性和动态行为,静态的属性、动态的方法,属性和方法是所在类的成员,属性和方法是构成一个类的主要部分。
依据尼古拉斯·沃斯的理论:程序本质上就是对数据的一种处理流程。任何流程都有基本的输入与输出,只有当输入遵循一定的规则时,输出才能达到预期的效果。这些输入的规则便是Python编码与命名规范等。
在生产制造行业有“模具是工业之母,IE(工业工程)是工业之父”的说法。IE在面向微观管理时有要求遵循“简单化、专业化、标准化”3个原则,并且一再强调“标准化是改善的基线”,由此可见规范的重要性。
以下是Python编码规则与注意事项:
(1)推荐每个import语句只导入一个模块,不建议一次导入多个模块。宜采用的导入方式如下:
#ch02d001.ipynb import numpy as np import pandas as pd
不建议采用以下方式导入模块:
import numpy as np,pandas as pd
在Python中有“模块、包、库”等术语,其中模块(module)是一个.py文件,文件名就是模块的名称,里面定义了函数、变量或类等,需要的时候可通过import命令导入。主要有以下几种导入方式:
import模块名 import模块名as别名 from模块名 import类名/函数名
包(package)是在模块之上的概念,模块是一个文件,包则存放了多个模块,相当于一个文件夹。原则上,只要文件夹包含__init__.py文件(该文件可以没有内容)则该文件夹就会被视为Python的一个包。假如其子目录文件夹内也有__init__.py,那么它就是这个包的子包。以获取Pandas的文件夹路径为例,代码如下:
import pandas as pd print(pd.__file__)
运行以上代码,返回的值如下:
D:\Users\HFX\anaconda3\lib\site-packages\pandas\__init__.py
可以通过资源浏览器访问该文件夹来查看xlwings中的所有模块、子包和子模块等。相对于Python中的内置模块与包而言,由第三方提供的包又称“第三方库”或“第三方模块”,例如本书所用到的NumPy、Pandas、Matplotlib、xlwings、openpyxl等都是第三方库,需要(用pip或conda)另外安装;不过在Anaconda中这些库都已经事先自动安装好了。
(2)推荐使用小括号对多行内容进行隐式连接,不建议采用反斜杆(\)进行连接。
宜采用的方式如下:
(df.groupby(['片区','包装方式']) .agg({'订单数':['mean',sum],'入库数':['size',sum,'mean']}) .pipe(y) ).head()
不建议采用以下方式:
df.groupby(['片区','包装方式'])\ .agg({'订单数':['mean',sum],'入库数':['size',sum,'mean']})\ .pipe(y)\ .head()
在每个族谱中都有各自的辈分名序,如果所有人都按照名序命名,则族人聚会时能够轻松了解到各自辈分的高低。当然,如果不按族谱名序命名也是可以的,但是族人聚会时信息的透明度与可比性就会下降很多。同理,在团队合作过程中,命名规范是很重要的,既方便自己日后维护,也方便团队共享与维护。
以下是Python中的一些命名规则举例:
(1)模块名全部使用小写字母;当模块名由两个或多个单词构成时,单词间用下画线连接。
(2)包名全部使用小写字母;当包名由两个或多个单词构成时,单词间用点(.)连接,例如matplotlib.pyplot。
(3)类名采用单词首字母大写,例如Path。
注意: 在Python中字母有严格的大小写区分。
保留字(或称关键字)是Python中一些已经被赋予特定意义的单词。在程序开发过程中,这些保留字不能再作为标识符给变量、函数、类、模板及其他对象命名。
在Python中,可通过以下方式查看所有保留字,代码如下:
import keyword print(keyword.kwlist)
运行以上代码,返回的值如下:
['False','None','True','__peg_parser__','and','as','assert','async','await','break','class', 'continue','def','del','elif','else','except','finally','for','from','global','if','import','in','is ','lambda','nonlocal','not','or','pass','raise','return','try','while','with','yield']
以上保留字是区别大小写的。例如将True写成true、将False写成false后用作变量或标识符是不受影响的,因为true与false不是Python中的关键字或保留字。
在Python使用过程中,不可以把这些保留字用作变量、函数、类、模块和其他对象的名称,否则会报错提示invalid syntax。应用举例:
and= '苏州' #SyntaxError:invalid syntax or= '杭州' #SyntaxError:invalid syntax
标识符主要用来标识变量、函数、类、模块和其他对象的名称。在Python中,标识符的命名规则如下:
(1)标识符由字母、下画线和数字构成,但首字符不能是数字。
(2)标识符中,不能包含空格、@、%及$等特殊字符。
(3)标识符不能和Python中的保留字相同。
在Python中,标识符严格区分大小写。应用举例,代码如下:
nws= '(华东)苏州' Nws = 512 NWS = 'sz'
在以上代码中:变量nws、Nws、NWS彼此独立且有效。利用id()查看各标识符或变量的地址。代码及返回的值如下:
id(nws) #2273574901328 id(Nws) #2273573510096 id(NWS) #2273469182512
当标识符中存在空格、@、%及$等特殊字符时将报错提示。应用举例如下:
@苏州 #SyntaxError:unexpected EOF while parsing %苏州 #UsageError:Line magic function`%苏州`not found $苏州 #SyntaxError:invalid syntax 苏州 #SyntaxError:invalid syntax
在Python中,变量是用于存储数据的内存空间,依据变量作用域的不同可分为“全局变量”和“局部变量”。将数据放入变量的过程叫作赋值,可通过“变量名=值”的方式来对变量赋值。在Python中,变量的命名与使用规则如下:
(1)变量必须是一个有效的标识符。
(2)不能使用Python中的保留字。
(3)宜选择有意义的字词作为变量。
(4)在Python中变量需要先定义后使用。
(5)命名时,同一字母的大小写代表的是不同变量。
变量赋值应用举例,代码如下:
nws= '(华东)苏州' va = 32
在以上代码中,nws、va为变量名,(华东)苏州、32为值。在变量赋值时遵循的是“无则新增、有则修改”的原则。例如对以上的nws变量重新赋值,代码如下:
nws= '(江苏)苏州' nws
返回的值为“(江苏)苏州”,原有的值“(华东)苏州”则被替换。在Python中可通过内置函数id()来查看变量的内存地址。应用举例,代码如下:
id(nws)
返回的值为2273573797200。
例如,使用未被事先定义的变量ws,代码如下:
print(ws)
此时返回的错误提示如下:
----------------------------------------------------------------- NameError Traceback(most recent call last) ~\AppData\Local\Temp/ipyKernel_12292/2210202466.py in<module> ---->1 print(ws) NameError:name 'ws'is not defined
在Python中,采用Tab键、2个空格或4个空格进行代码缩进,但是,出于跨平台兼容性考虑,在代码缩进过程中不建议Tab键与空格键混合使用,因为不同平台间对于一个Tab键占据多少个空格是没有统一规定的。如此下来会造成平台切换后因代码不整齐而运行报错。代码缩进,应用举例:
… ws2.title= '苏州' for i in range(1,ws1.max_row+1): for j in range(1,ws1.max_column+1): ws2.cell(row = i,column = j).value = ws1.cell(row = i,column = j).value
在以上代码中,流程控制语句行尾的冒号(:)和下一行的缩进代表一个代码块的开始,而缩进的结束则代表该代码块的结束。
在Python中有单行注释和多行注释之分。
在Python中,使用#接注释内容。从#开始至换行为止,#后面所接的内容将被作为注释内容而被Python编译器所忽略。应用举例,代码如下:
#'该行为注释,不会被编译' #-*-coding:utf-8-*- #中文编码声明注释 from pathlib import Path #导入pathlib模块中的Path from openpyxl import load_workbook #导入openpyxl模块中的load_workbook
在Python中,使用三单引号或三双引号进行多行注释。三单引号或三双引号间的多行内容均会被作为注释内容而被Python编译器所忽略。应用举例,代码如下:
""" Created on Wed Feb 1 16:59:01 2023 @author:HFX 《从Excel到Python数据分析》 -*-Pandas、xlwings、openpyxl、Matplotlib的交互与应用 """
以上多行注释也可写成如下形式:
#Created on Wed Feb 1 16:59:01 2023 #@author:HFX #《从Excel到Python数据分析》 #-*-Pandas、xlwings、openpyxl、Matplotlib的交互与应用
在Python中,可通过调用input()内置函数实现信息的输入,通过print()内置函数实现信息的输出。这两个函数的语法如下:
input([prompt]) print(value,…,sep = '',end = '\n')
数据结构就是数据与数据之间的关系。在Python中,主要有列表、元组、字典、集合这4种数据结构,可理解为4种容器。这些数据结构之间是可以进行相互转换的;各结构内的元素可以通过遍历或其他方式获取具体值。
列表是一个有序、可变、可重复的数据集,相当于C++、Java等语言中的数组,功能十分强大。在Python中,列表有很多优点,例如通过偏移来索引、支持嵌套、可变的类型。列表常用于以下操作:切片/索引、生成新列、删除、修改并重新赋值、成员关系的判断、列表推导、可转换为其他的数据结构等。
可以使用以下两种方式创建空列表,代码如下:
#ch02d002.ipynb lst = [] #lst = list()
创建列表lst1、lst2,代码如下:
lst1 = ['上海','南京','常州','无锡','苏州'] lst2 = ['厦门','合肥','宁波','杭州'] lst3 = [0,1,2,3,4] lst4 = [[5,6,7,8]]
对列表lst1、lst2进行相加,代码如下:
lst1+lst2
返回的值如下:
['上海','南京','常州','无锡','苏州','厦门','合肥','宁波','杭州']
对列表lst1、lst3进行相加,代码如下:
lst1+lst3
在同一列表中允许存在不同的数据类型。返回的值如下:
['上海','南京','常州','无锡','苏州',0,1,2,3,4]
对列表lst1、lst4进行相加,代码如下:
lst1+lst4
在同一列表中允许存在多维的列表。返回的值如下:
['上海','南京','常州','无锡','苏州',[5,6,7,8]]
对列表lst2重复2次,代码如下:
lst2 * 2
返回的值如下:
['厦门','合肥','宁波','杭州','厦门','合肥','宁波','杭州']
在Python中常用的列表函数见表2-1。
表2-1 Python中常用的列表函数
以上函数的x参数为对象,i参数为下标索引值(从0开始计算)。list.extend(seq)中的seq参数为另外一个列表。在Python的列表中,每个元素都有数字下标,代表在列表中的位置,这个位置就是索引,所以也常称为下标索引或下标索引值。
Python中列表函数append()应用举例,代码如下:
ln = [2,8,9,3,3,3,9,2,5,3,8,3] ln1 = [1,2,3,4] ln.append(ln1) ln
列表ln1将作为一个列表整体追加到列表ln的尾部。返回的值如下:
[2,8,9,3,3,3,9,2,5,3,8,3,[1,2,3,4]]
列表函数extend()应用举例,代码如下:
ln = [2,8,9,3,3,3,9,2,5,3,8,3] ln1 = [1,2,3,4] ln.extend(ln1) ln
将列表ln1中的全部元素追加到列表ln的尾部。返回的值如下:
[2,8,9,3,3,3,9,2,5,3,8,3,1,2,3,4]
列表函数insert()应用举例,代码如下:
ln = [2,8,9,3,3,3,9,2,5,3,8,3] ln.insert(3,2893) ln
在列表ln下标值3的位置(下标值从0开始)插入2893。返回的值如下:
[2,8,9,2893,3,3,3,9,2,5,3,8,3]
列表函数remove()应用举例,代码如下:
ln.remove(2893) ln
在列表ln中移除2893。返回的值如下:
[2,8,9,3,3,3,9,2,5,3,8,3]
列表函数pop()从列表ln中弹出最后一个值,代码如下:
ln.pop() ln
在列表ln中移除最后一个值3。返回的值如下:
[2,8,9,3,3,3,9,2,5,3,8]
从列表ln现存值中下标为3的位置弹出该值,代码如下:
ln.pop(3) ln
返回的值如下:
[2,8,9,3,3,9,2,5,3,8]
列表函数index(x)从列表ln现存值查找数值8的下标索引位置,代码如下:
ln.index(8)
返回值为1。其他函数用法不再一一举例。
对于列表可利用索引或切片进行访问。创建列表如下:
lst = ['上海','南京','常州','无锡','苏州','厦门','合肥','宁波','杭州']
对其进行索引(Python中的下标索引值是从0开始计算的)。索引或切片时,可以为正数索引,也可以是负数索引;正数索引时,应用举例,代码如下:
lst[3]
返回的值为“无锡”。利用切片对列表进行访问,代码如下:
lst[3:7]
在Python中切片为左闭右开,返回的值如下:
['无锡','苏州','厦门','合肥']
应用举例,采用负数索引,代码如下:
lst[-5:-2]
返回的值如下:
['苏州','厦门','合肥']
在实际使用过程中,会经常对列表进行遍历,相关知识在循环结构部分进行讲解。
元组是与列表类似的数据结构。元组是一个有序、不可变、可重复的数据集,相邻元素用逗号隔开。其区别在于:列表为中括号,元组为小括号,元组内的数据不可更改。可以使用以下两种方式创建空元组,代码如下:
tple = () #tple = tuple() type(tple)
创建一个值的元组,代码如下:
tpl = (2,) type(tpl)
返回的值为tuple。
注意: 当元组中只有一个值时,值后面的逗号不能省略。
继续创建元组,代码如下:
tp = (2,8,9,3,3,3,9,2,5,3,8,3)
元组计算应用举例(右侧备注为返回的值),代码如下:
max(tp) #9 min(tp) #2 len(tp) #12 tp.count(3) #5
与列表一样,可以对元组进行索引或切片,代码如下:
tp[3] #3 tp[3:7] #(3,3,3,9)
如果对元组进行数据修改,则会报错提示。应用举例:
tp.reverse() tp
返回的报错提示如下:
AttributeError:'tuple'object has no attribute 'reverse'
字典是一个无序、可变、可重复的数据集。字典也称键-值对,它是通过键来将一系列的值串接起来的,可以通过键从字典中获取指定项。字典是通过大括号来创建的。字典中的键必须是唯一且不可变的,键可以是数字、字符串或元组,但不能是列表,每个键与值之间用冒号隔开,每一对键值之间用逗号隔开。
可以使用以下两种方式创建一个空字典,代码如下:
dic = dict() #dic = {}
继续创建字典,代码如下:
dic1 = {'蛋糕纸':'纸盒','苹果醋':'酸醋'} dic2 = {'语文':[95,85,],'数学':[93,87,]}
dic1中的值为字符串,dic2中的值为列表。查看这两个字典的数据类型,代码如下:
print(type(dic),type(dic1),type(dic2))
返回的值如下:
<class 'dict'><class 'dict'><class 'dict'>
在Python中,类与对象的区别:抽象的类(class),具体的对象(object)。
字典可以任意嵌套,值由列表及元组构成,代码如下:
查看其数据类型。
type(dct) #dict
查看字典的items,代码如下:
print(dct.items())
返回的值如下:
dct_items([('华北',[('华北','北京','DD001','蛋糕纸',2,2)]),('华东',[('华东','上海','D D003','苹果醋',2,2),('华东','宁波','DD004','钢化膜',1,1)])])
对字典进行访问是通过键来读取的,代码如下:
dct['华北']
返回的值如下:
[('华北','北京','DD001','蛋糕纸',2,2)]
如果该键不存在,则会报错提示。应用举例:
dct['华西']
返回的错误提示如下:
KeyError Traceback(most recent call last) ~\AppData\Local\Temp/ipyKernel_9252/3152721856.py in<module> ---->1 dct['华西'] KeyError:'华西'
在字典遍历过程中,常用的3种方法为keys()、values()、items()。应用举例,遍历字典中的keys(),代码如下:
for k in dct.keys(): print(k)
运行以上代码,返回的值如下:
华北 华东
应用举例,遍历字典中的values(),代码如下:
for v in dct.values(): print(v)
运行以上代码,返回的值如下:
[('华北','北京','DD001','蛋糕纸',2,2)] [('华东','上海','DD003','苹果醋',2,2),('华东','宁波','DD004','钢化膜',1,1)]
应用举例,遍历字典中的键值items(),代码如下:
for i in dct.items(): print(i)
运行以上代码,返回的值如下:
('华北',[('华北','北京','DD001','蛋糕纸',2,2)]) ('华东',[('华东','上海','DD003','苹果醋',2,2),('华东','宁波','DD004','钢化膜',1,1)])
应用举例,通过遍历字典以获取具体的每个key值,代码如下:
for key,value in dct.items(): print(key)
在以上代码中循环变量key和value采用k、v或其他命名方式是允许的。返回的值如下:
华北 西南 华东
应用举例,通过遍历字典以获取具体的每个value值,代码如下:
for key,value in dct.items(): print(value)
返回的值如下:
[('华北','北京','DD001','蛋糕纸',2,2)] [('华东','上海','DD003','苹果醋',2,2),('华东','宁波','DD004','钢化膜',1,1)]
或者直接采用keys()、values()、items(),返回列表值,代码如下:
print(dct.keys()) #dict_keys数据类型 print(dct.values()) #dict_values数据类型 print(dct.items()) #dict_items数据类型
在Python中,集合是一个无序、不可重复的数据集。集合有可变集合(set)和不可变集合(frozenset)两种。
(1)集合具备去重功能,当集合中存在重复的元素时会自动保留一个。
(2)集合是无序的,集合内各元素出现的位置每次都会不同。
(3)Python中的集合与数学中的集合概念类似,可以对其进行并集、交集、差集及补集等操作。
字典是通过大括号{}来创建的,相邻元素间用逗号(,)分开。可用set()创建空白集合。Python中集合常用的方法见表2-2。
表2-2 Python中集合常用的方法
以上方法中,a和b各自代表的是一个数据的集合,x代表的是集合中的元素。
集合中union()方法应用举例,代码如下:
a = {'上海','南京','常州','无锡','苏州'} b = {'南京','常州','宁波','杭州'} c = a.union(b) #a|b c
在新的集合c中,返回的是集合a与b的并集,返回的值如下:
{'上海','南京','宁波','常州','无锡','杭州','苏州'}
update()方法用于修改当前集合,可以将新的元素或集合添加到当前集合中(添加的过程中会自动添加重复的元素)。集合中update()方法应用举例,代码如下:
a = {'上海','南京','常州','无锡','苏州'} b = {'南京','常州','宁波','杭州'} a.update(b) #a| = b a
在修改后的集合a中,在添加集合b中所有元素的同时并删除了在a集合中重复的元素,返回的值如下:
{'上海','南京','宁波','常州','无锡','杭州','苏州'}
集合中intersection()方法应用举例,代码如下:
a = {'上海','南京','常州','无锡','苏州'} b = {'南京','常州','宁波','杭州'} c = a.intersection(b) #c = a&b c
在新的集合c中,返回的是集合a与b的交集,返回的值如下:
{'南京','常州'}
集合中intersection_update()方法应用举例,代码如下:
a = {'上海','南京','常州','无锡','苏州'} b = {'南京','常州','宁波','杭州'} a.intersection_update(b) #a& = b a
返回的值如下:
{'南京','常州'}
集合中add()方法应用举例,代码如下:
a = {'上海','南京','常州','无锡','苏州'} a.add('杭州') a
返回的值如下:
{'上海','南京','常州','无锡','杭州','苏州'}
超集检查issuperset()方法应用举例,代码如下:
a = {'上海','南京','常州','无锡','苏州'} b = {'南京','常州'} a.issuperset(b) #a>b
返回的值为True。
在Python中,数值型、字符串型、布尔型是最基本的3种数据类型。应用举例如下:
rng.font.name= '楷体' rng.font.size = 20 rng.font.bold = True
在以上代码中,“楷体”为字符串型、20为数值型、True为布尔型。
在Python中,主要支持的数值类型有整数(int)、浮点数(float)、复数(complex)。
在Python中,单行的字符串可通过单引号('')、双引号("")引起来,二者之间没有差别。多行的字符串可通过三引号(三单引号''''''、三双引号"""""")引起来,二者之间同样没有差别。
在Python中,数值与字符串属于不同的数据类型,二者之间不可以直接相加。应用举例如下:
'苏州'+512
运行以上代码,返回的错误提示如下:
如果将其中的数值转换为文本字符串,然后相加,则没有问题,代码如下:
'苏州'+str(512) #'苏州512'
在以上代码中,内置函数str()用于将对象的值转换为字符串类型。在Python中各类常用内置转换函数见表2-3。
表2-3 Python中各类常用内置转换函数
在Python中,∗操作符用于整型或浮点型数值间表示乘法(例如5∗6,返回的值为30),当作为字符串时代表字符串重复的次数(只能为整型,不能为浮点型)。应用举例如下:
'苏州'*5 #'苏州苏州苏州苏州苏州'
更多有关字符串及正则用法可参见本书5.1节(字符串处理)。
Python中字符串是支持转义字符的。Python中常见的转义字符见表2-4。
表2-4 Python中常见的转义字符
转义字符应用举例,以\n(换行为例),在字符串中增加转义字符\n,代码如下:
#ch02d003.ipynb print('上海','南京','宁波\n','常州','无锡\n','杭州','苏州')
运行以上代码,显示的结果如下:
上海,南京,宁波 常州,无锡 杭州 苏州
在Python中,常采用f-string、format()方法、%操作符这3种方式来格式化字符串,其中f-string比format()方法、%操作符更为便捷好用。
1)f-string
f-string格式字符串时,引号前面使用f或F均可,引号内{}用于存放变量。应用举例如下:
for i in range(1,4): print(f'工作簿{i}.xlsx')
运行以上代码,返回的值如下:
工作簿1.xlsx 工作簿2.xlsx 工作簿3.xlsx
f-string也可以用于输出表达式及计算结果。应用举例,代码如下:
for i in range(1,4): print(f'{i+10 = }')
运行以上代码,返回的值如下:
i+10 = 11 i+10 = 12 i+10 = 13
2)format()方法
format()方法的语法如下:
'{}'.format()
采用format()方法格式字符串时,较常用的占位字符有s(字符串)、d(十进制整数)、f或F(浮点数)、%(百分比),其他的占位字符有c、e或E、g或G、x或X、b、o。应用举例如下:
for i in range(1,4): print('工作簿{:s}'.format(str(i)))
在以上代码中,先将数据类型由int转换为str,然后对str进行格式化。运行以上代码,返回的值如下:
工作簿 1 工作簿 2 工作簿 3
应用举例,将列表中的整型数据转换为带两位小数的浮点型数据,代码如下:
for i in range(1,4): print('{:.2f}'.format(i))
运行以上代码,返回的值如下:
1.00 2.00 3.00
继续举例,将列表中的整型数据转换为带两位小数的百分位数据,代码如下:
for i in range(1,4): print('{:.2%}'.format(i))
运行以上代码,返回的值如下:
100.00% 200.00% 300.00%
3)%操作符
在Python中也可以使用%操作符来格式化字符串。较常用的占位字符有%s(字符串)、%d或%i(十进制整数)、%f或%F(浮点数)、%%(百分比),其他的占位字符有%c、%e或%E、%x、%r、%o。应用举例,采用%d占位,代码如下:
for r in range(1,4): print('工作簿% d.xlsx' % r)
或者采用%i占位,代码如下:
for r in range(1,4): print('工作簿 % i.xlsx' % r)
运行以上代码,返回的值如下:
工作簿1.xlsx 工作簿2.xlsx 工作簿3.xlsx
在Python中,对比运算、逻辑运算的返回值可用布尔型True或False来表示。在参与数值计算时,布尔型可以转换为数值型,例如将True转换为1、将False转换为0。
注意: 在Python中,True、False的首字母必须为大写。
在Python中,为了实现项目的某一需求或具体功能,需采用运算符和表达式将变量、字符串等关系进行组合并表达出来。Python中的运算符有算术运算符、比较运算符、逻辑运算符、赋值运算符、位运算符、成员运算符(in、not in)、身份运算符(is、is not)。
在Python中主要有+(加)、-(减)、∗(乘)、/(除)、%(求余)、//(取整)、∗∗(幂)这几个算术运算符。应用举例如下:
#ch02d004.ipynb 9+2 #11 9-2 #7 9 * 2 #18 9/2 #4.5 9%2 #1 9//2 #4 9 * *2 #81
运算的优先级,先乘除后加减,括号优先;同一优先级按从左到右的顺序运行。应用举例如下:
2+3 * 4 #14 (2+3)* 4 #20 2 * 3+2 * 4 #14
在Python中主要有=(赋值)、+=(加赋值)、-=(减赋值)、∗=(乘赋值)、/=(除赋值)、%=(取余数赋值)、//=(取整除赋值)、∗∗=(幂赋值)这几个赋值运算符。
+=(加赋值)应用举例,代码如下:
a = 9 b = 2 a+ = b #a = a+b a #11
-=(减赋值)应用举例,代码如下:
a = 9 b = 2 a- = b #a = a-b a #7
∗=(乘赋值)应用举例,代码如下:
a = 9 b = 2 a * =b #a=a * b a #18
/=(除赋值)应用举例,代码如下:
a = 9 b = 2 a/ = b #a = a/b a #4.5
%=(取余数赋值)应用举例,代码如下:
a = 9 b = 2 a% = b #a = a%b a #1
//=(取整除赋值)应用举例,代码如下:
a = 9 b = 2 a// = b #a = a//b a #4
∗∗=(幂赋值)应用举例,代码如下:
a = 9 b = 2 a * * =b #a=a * * b a #81
在Python中主要有==(等于)、!=(不等于)>=(大于或等于)、<=(小于或等于)、>(大于)、<(小于)这几个比较运算符,返回的值为布尔值True与False。
应用举例,先创建变量a和b,代码如下:
a = 9 b = 2
对变量a和b进行比较运算,代码如下:
a = = b #False a! = b #True a> = b #True a< = b #False a>b #True a<b #False
Python中的布尔逻辑运算符是and(与)、or(与)和not(非),3种逻辑运算的优先级为not>and>or,代码如下:
True #True False #False not True #False not False #True True and False #False 5< 10 and 3>4 #False True or False #True 5< 10 or 3>4 #True True and True #True 3 = = 3 and None! = 3 #True True and False #False True and 3>4 #False
以上代码返回值所用逻辑运算见表2-5。
表2-5 逻辑运算
位运算符是把数字看成二进制数进行计算。Python中的位运算符有&(位与)、|(位或)、^(位异或)、~(位取反)、<<(位左移)、>>(位右移)位运算符。在进行位运算之前需先将相关数值转换为二进制,然后进行计算。
以(十进制)数字2002及1999为例,这两个十进制数字对应的二进制数字分别为0111 1101 0010、0111 1100 1111。对2002及1999进行位与运算,代码如下:
2002&1999
返回的十进制数字为1986(对应的二进制数字为0111 1100 0010)。相关运算过程如图2-2所示。
应用举例,以(十进制)数字5向左移8位为例,代码如下:
5<<8 #左移动运算符 #1280
在移位的过程中,左边(高位端)溢出的位会被丢弃,右边(低位端)的空位会被补0。(十进制)数字5对应的二进制数字为0101,左移位补0后的二进制数字为0101 0000 0000(对应的十进制数字为1280)。相关运算过程如图2-3所示。
图2-2 运算过程1
图2-3 运算过程2
算法本质上就是解决具体计算问题的实施步骤。可以用“顺序、分支、循环”这3种控制结构实现,如图2-4所示。
图2-4 控制结构
顺序结构比较容易理解。应用举例,代码如下:
#ch02d005.ipynb a = int(input('请输入订单数:')) b = a * a print('订单数的平方为',b)
运行以上代码,必须先输入a的值才可以得到b的值。假如输入的a值为12,返回的值如下:
请输入订单数:12 订单数的平方为144
在Python中有if、if-else、if-elif-else这3种常用分支选择语句。
在Python中if是保留字,用于语句中的分支选择,其语法如下:
if条件表达式: 条件(分支选择)语句
以简单的if条件判断举例。如果输入的城市名为广州,则返回显示“一线城市:广州”,代码如下:
city= '广州' if city== '广州': print('一线城市:广州')
或者采用赋值表达式的写法,代码如下:
if(city:='广州')== '广州': print('一线城市:广州')
在以上代码中赋值表达式(∶=)是Python 3.8中新增的语法,该语法的表达式如下:
(variable_name: = expression or value)
运行以上两个等效的代码,返回的值如下:
一线城市:广州
以双条件为判断依据。如果输入的订单数为大于10且小于20,则返回显示“订单数:10~20”,代码如下:
if(订单数: = 15)>10 and订单数<20: print('订单数:10~20')
运行以上代码,返回的值如下:
订单数:10~20
在Python中,if-else-条件表达式适用于“if语句1 else语句2”的应用场景,else子句后面不接条件判断。应用举例,在现有列表中属于华南区域的城市有“广州、深圳、珠海”,如果输入的城市为其中之一,则返回“华南区:广州|深圳|珠海”;如果输入任意城市(例如惠州),则会显示“该城市不在华南区的列表中”,代码如下:
city= input('请输入城市名:') if city = = '广州'or city = = '深圳'or city = = '珠海': print('华南区:',city) else: print('该城市不在华南区的列表中')
运行以上代码,输入“广州”,返回的值如下:
请输入城市名:广州 华南区:广州
在Python中,if-elif-else-多条件表达式类似于其他计算机语言中Switch多条件分支所实现的功能,else子句后面不接条件判断,其语法如下:
if条件表达式1: 语句1 elif条件表达式2: 语句2 elif条件表达式3: 语句3 … else: 语句n
if-elif-else-多条件表达式应用举例,代码如下:
num= int(input('请输入订单数:')) if num>20: print('你输错了!') elif num>10: print('订单数>10') elif num>5: print('订单数>5') else: print('小批量订单!')
运行以上代码,输入订单数12,返回的值如下:
请输入订单数:22 你输错了!
循环是指重复做同一件事情。在Python中主要有for循环与while循环两种,其中for循环为计数循环,同一件事情重复做多少次;while循环为条件循环,只要符合条件就一直循环下去,直到不符合条件时才结束。为了避免出现死循环现象,Python中还提供了break、continue等语句。break用于终止当前循环并结束整个循环,continue用于跳过本次循环的剩余语句并开始新的一轮循环。另外,Python还推出了一个为保持程序结构完整而使用的pass空语句,用于占位。
for循环的语法如下:
for循环变量 in对象: 循环体
应用举例,循环列表中的值,如果字符是以州结尾,则将该字符改为字母Z,代码如下:
for i in['上海','南京','常州','无锡','苏州']: if i.endswith('州'): i = i.replace('州','Z') print(i)
运行以上代码,返回的值如下:
上海 南京 常Z 无锡 苏Z
继续应用举例,对原有列表进行判断并添加新值,代码如下:
lst = ['上海','南京','常州','无锡','苏州'] for i in lst: if '杭州'not in lst: lst.append('杭州') print(lst)
运行以上代码,由于原列中不存在杭州,因此杭州被添加到列表中,返回的值如下:
['上海','南京','常州','无锡','苏州','杭州']
继续应用举例,创建一个空列表,用于存储循环过程中符合的值,代码如下:
ls = [] lst = ['~$','上海','南京','常州','无锡','苏州'] for x in lst: if x.startswith('~'): continue ls.append(x) print(ls)
运行以上代码,由于原列中的第1个值不符合条件而被筛选移除,返回的值如下:
['上海','南京','常州','无锡','苏州']
while循环的语法如下:
while条件表达式: 循环体
while循环应用举例,代码如下:
i = 1 #控制循环次数并存储值 while i< = 3: i+ = 1 print(f'i的值为{i}')
运行以上代码,返回的值如下:
i的值为2 i的值为3 i的值为4
继续举例,代码如下:
i = 1 #控制循环次数 z = 0 #存储计算结果 while i< = 3: z+ = i i+ = 1 print(f'z的值为{z}')
运行以上代码,返回的值如下:
z的值为1 z的值为3 z的值为6
在Python中可采用列表、字典、集合的推导式来代替换for循环。以列表推导式为例,在采用for循环时,代码如下:
lst = [] for i in['杭州','苏州']: lst.append(pd.read_excel(r'D:\数据源\B文件\华东.xlsx',i))
采用列有推导式,代码如下:
lst = [pd.read_excel(r'D:\数据源\B文件\华东.xlsx',i)for i in['杭州','苏州']]
以上两种方式所实现的功能是等效的。
在Python中,迭代器是一个可以记遍历位置的对象。可迭代的对象,通俗地讲就是可以用for循环作用的数据对象(如列表、元组、字典、集合、字符串)。在Python中,主要有两个内置迭代器协议方法:iter()方法和next()方法。
应用举例,使用for循环语句遍历迭代器,代码如下:
lst = ['上海','南京','常州','无锡','苏州'] it= iter(lst) for i in it: print(i,end = '')
运行代码,返回的值如下:
上海南京常州无锡苏州
应用举例,采用next调用迭代器举例,代码如下:
it= iter(lst) next(it) #'上海' next(it) #'南京' next(it) #'常州' next(it) #'无锡' next(it) #'苏州'
在Python中,一边循环一边计算的机制称为生成器(generator)。当运行的数据量过大时,采用生成器方式可极大地节约内存空间。应用举例,将列表推导式中最外层的[]改成(),创建生成器,代码如下:
g = (pd.read_excel(r'D:\数据源\B文件\华东.xlsx',i)for i in['杭州','苏州']) print(g)
运行以上代码,返回的值如下:
<generator object<genexpr>at 0x00000294BF753660>
此时可采用迭代方式调用生成器。以next()函数调用为例,代码如下:
next(g)
运行以上代码,第1次调用生成器,返回的值如下:
片区 订单来源 接单时间 订单编号 包装方式 产品 订单数 入库日期 入库数 0 华东 杭州 2021-07-27 DD022 散装 钢化膜 7 2021-08-03 16:31:42 7 1 华东 杭州 2021-08-03 DD020 桶装 油漆 8 2021-08-03 08:20:33 8 2 华东 杭州 2021-08-03 DD021 捆 木材 13 2021-08-04 08:58:55 13
继续以next()函数调用,代码如下:
next(g)
运行以上代码,第2次调用生成器,返回的值如下:
片区 订单来源 接单时间 订单编号 包装方式 产品 订单数 入库日期 入库数 0 华东 苏州 2021-06-24 DD015 袋 劳保手套 2 2021-06-27 21:19:00 2 1 华东 苏州 2021-06-30 DD016 扎 包装绳 3 2021-07-01 15:58:50 3 2 华东 苏州 2021-07-01 DD01 桶装 油漆 6 2021-07-02 02:00:38 6 3 华东 苏州 2021-07-02 DD017 捆 木材 16 2021-07-02 07:08:58 13
代码如下:
g = (pd.read_excel(r'D:\数据源\B文件\华东.xlsx',i)for i in['杭州','苏州']) for i in g: print(i)
运行以上代码,返回的值如下:
片区 订单来源 接单时间 订单编号 包装方式 产品 订单数 入库日期 入库数 0 华东 杭州2021-07-27 DD022 散装 钢化膜 7 2021-08-03 16:31:42 7 1 华东 杭州2021-08-03 DD020 桶装 油漆 8 2021-08-03 08:20:33 8 2 华东 杭州2021-08-03 DD021 捆 木材 13 2021-08-04 08:58:55 13 片区 订单来源 接单时间 订单编号 包装方式 产品 订单数 入库日期 入库数 0 华东 苏州2021-06-24 DD015 袋 劳保手套 2 2021-06-27 21:19:00 2 1 华东 苏州2021-06-30 DD016 扎 包装绳 3 2021-07-01 15:58:50 3 2 华东 苏州2021-07-01 DD014 桶装 油漆 6 2021-07-02 02:00:38 6 3 华东 苏州2021-07-02 DD017 捆 木材 16 2021-07-02 07:08:58 13
在Python中,也可通过yield函数创建生成器,此处不再举例。关于装饰器的相关知识本书不进行介绍。
在IDE或IDLE中,可通过print(dir(__builtins__))命令查看所有的Python内置函数:
#ch02d006.ipynb print(dir(__builtins__))
运行以上代码,返回的值如下:
['ArithmeticError','AssertionError','AttributeError','BaseException','BlockingIOError', 'BrokenPipeError','BufferError','BytesWarning','ChildProcessError','ConnectionAbortedError', 'ConnectionError','ConnectionRefusedError','ConnectionResetError','DeprecationWarning', 'EOFError','Ellipsis','EnvironmentError','Exception','False','FileExistsError', 'FileNotFoundError','FloatingPointError','FutureWarning','GeneratorExit','IOError', 'ImportError','ImportWarning','IndentationError','IndexError','InterruptedError', 'IsADirectoryError','KeyError','KeyboardInterrupt','LookupError','MemoryError', 'ModuleNotFoundError','NameError','None','NotADirectoryError','NotImplemented', 'NotImplementedError','OSError','OverflowError','PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError','RecursionError','ReferenceError','ResourceWarning', 'RuntimeError', 'RuntimeWarning','StopAsyncIteration','StopIteration','SyntaxError', 'SyntaxWarning', 'SystemError','SystemExit','TabError','TimeoutError','True','TypeError', 'UnboundLocalError', 'UnicodeDecodeError ','UnicodeEncodeError','UnicodeError', 'UnicodeTranslateError', '__'UnicodeWarning','UserWarning','ValueError','Warning','WindowsError', 'ZeroDivisionError', IPYTHON__','__build_class__','__Debug__','__doc__','__import__', '__loader__','__name__','__package__','__spec__','abs','all','any','ascii','bin','bool', 'breakpoint','Bytearray',' Bytes','callable','chr','classmethod','compile','complex', 'copyright','credits','delattr',' dict','dir','display','divmod','enumerate','eval','exec', 'execfile','filter','float','format',' frozenset','get_ipython','getattr','globals','hasattr', 'hash','help','hex','id','input','int','isinstance','issubclass','iter','len','license', 'list','locals','map','max','memoryview','min','next','object','oct','open','ord','pow', 'print','property','range','repr',' reversed','round','runfile','set','setattr','slice', 'sorted','staticmethod','str','sum','super','tuple','type','vars','zip']
对比以上内置函数后不难发现,例如在以上代码中所用到的print()、dir()函数就是Python的内置函数。
以内置函数zip()为例,该函数用于将可迭代的对象打包成元组并返回由元组组成的对象,代码如下:
a = ['散装','桶装','捆'] b = ['钢化膜','油漆','木材'] c = [7,8,13] lst = zip(a,b,c) print(lst)
运行以上代码,返回的值如下:
<zip object at 0x0000021BE942F4C0>
继续举例,代码如下:
print(list(lst))
运行以上代码,返回的值如下:
[('散装','钢化膜',7),('桶装','油漆',8),('捆','木材',13)]
继续举例,代码如下:
zip(* [a,b,c])
运行以上代码,返回的值如下:
<zip object at 0x0000021BE942F700>
遍历zip可迭代对象,代码如下:
for i in zip(* [a,b,c]): print(i)
运行以上代码,返回的值如下:
('散装','钢化膜',7) ('桶装','油漆',8) ('捆','木材',13)
在Python代码开发过程中,对于多次调用的某段代码或出于代码简洁性考虑的某段代码,可以将其创建为自定义函数而供调用。在Python中自定义函数的语法如下:
def函数名(参数列表): '''函数的备注''' 函数的主体内容 return返回的对象
自定义函数的基础编码规则如下:
(1)函数名以def关键字开头,以冒号结尾,参数列表用小括号括起来。
(2)函数内容以冒号开始,并且内容要缩进。
(3)用“return表达式”结束函数,该参数为可省参数。
应用举例,创建自定义函数cfx,将字符串“订单”替换为DD,代码如下:
def cfx(x): return x.replace("订单","DD") lst = ['订单来源','订单编号','订单数'] for i in lst: i = cfx(i) print(i)
运行以上代码,返回的值如下:
DD来源 DD编号 DD数
匿名函数是指没有名字的函数,适用于只需调用一次且代码简短的场合。在Python中,可通过lambda表达式来创建匿名函数,语法如下:
result = lambda[args]:expression
匿名函数可以先赋值给一个变量再进行调用。(变量)result用于调用lambda表达式,arg参数为可选参数,用于指定要传递的参数列表,expression为必选参数。
应用举例,利用匿名函数,将字符串“订单”替换为DD,代码如下:
lst = ['订单来源','订单编号','订单数'] for i in lst: lmx = lambda i:i.replace("订单","DD") print(lmx(i))
运行以上代码,返回的值如下:
DD来源 DD编号 DD数
异常是指程序在运行过程中所发生的各种错误或不正常。
Python中常用的内置预定义的异常见表2-6。
表2-6 Python中常用的内置预定义的异常
在Python中,可采用try-except、try-except-else、try-except-finally语句来处理异常。先产生一条错误提示,代码如下:
dct = {'华北':'北京','华东':'上海','华南':'广州'} dct['华西']
运行以上代码,返回的错误提示如下:
------------------------------------------------------------- KeyError Traceback(most recent call last) ~\AppData\Local\Temp\ipyKernel_9264\3736228760.py in<module> 1 dct = {'华北':'北京','华东':'上海','华南':'广州'} ---->2 dct['华西'] KeyError:'华西'
以try-except-finally为例进行异常处理,代码如下:
try: print(dct['华西']) except KeyError: print('你确定字典的键存在华西?') finally: print('输入之前先检查!')
在以上代码中,try子句后面所跟的是可能发生异常的语句,except子句用于捕获指定的异常,finally子句用于离开try-except时最后执行的语句。运行以上代码,返回的异常处理提示如下:
你确定字典的键存在华西? 输入之前先检查!