购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

第2章
Python基础入门

Pascal之父,尼古拉斯·沃斯(Nicklaus Wirth)有这么一句名言:程序(Program)=算法(Algorithm)+数据结构(Data Structure)。依据该理论,本章将从“程序=数据+算法”的角度进行展开,其中数据分为数据结构和数据类型。结构决定功能,功能一般通过相关的算法(函数或方法)及其控制结构实现,如图2-1所示。

图2-1 程序的构成

2.1 程序设计

Python是一门面向对象编程的语言,它具备丰富的库,能够轻松地与其他语言进行连接,因此Python语言也经常被称为“胶水”语言。在Python中,“类、成员、对象、属性、方法”是面向对象编程的几个核心概念。例如把具有相同属性和方法的对象归为一个类(class),“物以类聚”,类是抽象的。对象是某个类中的每个实体,对象是类的实例化结果,万物皆对象,对象是具体存在的事物。对象可以有自己的属性和动态行为,静态的属性、动态的方法,属性和方法是所在类的成员,属性和方法是构成一个类的主要部分。

2.1.1 编码规范

依据尼古拉斯·沃斯的理论:程序本质上就是对数据的一种处理流程。任何流程都有基本的输入与输出,只有当输入遵循一定的规则时,输出才能达到预期的效果。这些输入的规则便是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()

2.1.2 命名规范

在每个族谱中都有各自的辈分名序,如果所有人都按照名序命名,则族人聚会时能够轻松了解到各自辈分的高低。当然,如果不按族谱名序命名也是可以的,但是族人聚会时信息的透明度与可比性就会下降很多。同理,在团队合作过程中,命名规范是很重要的,既方便自己日后维护,也方便团队共享与维护。

以下是Python中的一些命名规则举例:

(1)模块名全部使用小写字母;当模块名由两个或多个单词构成时,单词间用下画线连接。

(2)包名全部使用小写字母;当包名由两个或多个单词构成时,单词间用点(.)连接,例如matplotlib.pyplot。

(3)类名采用单词首字母大写,例如Path。

注意: 在Python中字母有严格的大小写区分。

2.1.3 保留字

保留字(或称关键字)是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

2.1.4 标识符

标识符主要用来标识变量、函数、类、模块和其他对象的名称。在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

2.1.5 变量

在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

2.1.6 代码缩进

在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

在以上代码中,流程控制语句行尾的冒号(:)和下一行的缩进代表一个代码块的开始,而缩进的结束则代表该代码块的结束。

2.1.7 注释

在Python中有单行注释和多行注释之分。

1.单行注释

在Python中,使用#接注释内容。从#开始至换行为止,#后面所接的内容将被作为注释内容而被Python编译器所忽略。应用举例,代码如下:

    #'该行为注释,不会被编译'
    #-*-coding:utf-8-*-              #中文编码声明注释
    from pathlib import Path              #导入pathlib模块中的Path
    from openpyxl import load_workbook    #导入openpyxl模块中的load_workbook
2.多行注释

在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的交互与应用

2.1.8 输入与输出

在Python中,可通过调用input()内置函数实现信息的输入,通过print()内置函数实现信息的输出。这两个函数的语法如下:

    input([prompt])
    print(value,…,sep = '',end = '\n')

2.2 数据结构

数据结构就是数据与数据之间的关系。在Python中,主要有列表、元组、字典、集合这4种数据结构,可理解为4种容器。这些数据结构之间是可以进行相互转换的;各结构内的元素可以通过遍历或其他方式获取具体值。

2.2.1 列表

列表是一个有序、可变、可重复的数据集,相当于C++、Java等语言中的数组,功能十分强大。在Python中,列表有很多优点,例如通过偏移来索引、支持嵌套、可变的类型。列表常用于以下操作:切片/索引、生成新列、删除、修改并重新赋值、成员关系的判断、列表推导、可转换为其他的数据结构等。

1.列表创建

可以使用以下两种方式创建空列表,代码如下:

    #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

返回的值如下:

    ['厦门','合肥','宁波','杭州','厦门','合肥','宁波','杭州']
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。其他函数用法不再一一举例。

3.列表访问

对于列表可利用索引或切片进行访问。创建列表如下:

    lst = ['上海','南京','常州','无锡','苏州','厦门','合肥','宁波','杭州']

对其进行索引(Python中的下标索引值是从0开始计算的)。索引或切片时,可以为正数索引,也可以是负数索引;正数索引时,应用举例,代码如下:

    lst[3]

返回的值为“无锡”。利用切片对列表进行访问,代码如下:

    lst[3:7]

在Python中切片为左闭右开,返回的值如下:

    ['无锡','苏州','厦门','合肥']

应用举例,采用负数索引,代码如下:

    lst[-5:-2]

返回的值如下:

    ['苏州','厦门','合肥']

在实际使用过程中,会经常对列表进行遍历,相关知识在循环结构部分进行讲解。

2.2.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'

2.2.3 字典

字典是一个无序、可变、可重复的数据集。字典也称键-值对,它是通过键来将一系列的值串接起来的,可以通过键从字典中获取指定项。字典是通过大括号来创建的。字典中的键必须是唯一且不可变的,键可以是数字、字符串或元组,但不能是列表,每个键与值之间用冒号隔开,每一对键值之间用逗号隔开。

1.字典创建

可以使用以下两种方式创建一个空字典,代码如下:

    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)])])
2.字典访问

对字典进行访问是通过键来读取的,代码如下:

    dct['华北']

返回的值如下:

    [('华北','北京','DD001','蛋糕纸',2,2)]

如果该键不存在,则会报错提示。应用举例:

    dct['华西']

返回的错误提示如下:

    KeyError             Traceback(most recent call last)
    ~\AppData\Local\Temp/ipyKernel_9252/3152721856.py in<module>
    ---->1 dct['华西']
     
    KeyError:'华西'
3.字典遍历

在字典遍历过程中,常用的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数据类型

2.2.4 集合

在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。

2.3 数据类型

在Python中,数值型、字符串型、布尔型是最基本的3种数据类型。应用举例如下:

    rng.font.name= '楷体'
    rng.font.size = 20
    rng.font.bold = True

在以上代码中,“楷体”为字符串型、20为数值型、True为布尔型。

2.3.1 数值型

在Python中,主要支持的数值类型有整数(int)、浮点数(float)、复数(complex)。

2.3.2 字符串型

1.普通字符串

在Python中,单行的字符串可通过单引号('')、双引号("")引起来,二者之间没有差别。多行的字符串可通过三引号(三单引号''''''、三双引号"""""")引起来,二者之间同样没有差别。

在Python中,数值与字符串属于不同的数据类型,二者之间不可以直接相加。应用举例如下:

    '苏州'+512

运行以上代码,返回的错误提示如下:

如果将其中的数值转换为文本字符串,然后相加,则没有问题,代码如下:

    '苏州'+str(512)                #'苏州512'

在以上代码中,内置函数str()用于将对象的值转换为字符串类型。在Python中各类常用内置转换函数见表2-3。

表2-3 Python中各类常用内置转换函数

在Python中,∗操作符用于整型或浮点型数值间表示乘法(例如5∗6,返回的值为30),当作为字符串时代表字符串重复的次数(只能为整型,不能为浮点型)。应用举例如下:

    '苏州'*5                     #'苏州苏州苏州苏州苏州'

更多有关字符串及正则用法可参见本书5.1节(字符串处理)。

2.转义字符

Python中字符串是支持转义字符的。Python中常见的转义字符见表2-4。

表2-4 Python中常见的转义字符

转义字符应用举例,以\n(换行为例),在字符串中增加转义字符\n,代码如下:

    #ch02d003.ipynb
    print('上海','南京','宁波\n','常州','无锡\n','杭州','苏州')

运行以上代码,显示的结果如下:

    上海,南京,宁波
     常州,无锡
     杭州 苏州
3.格式化字符串

在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

2.3.3 布尔型

在Python中,对比运算、逻辑运算的返回值可用布尔型True或False来表示。在参与数值计算时,布尔型可以转换为数值型,例如将True转换为1、将False转换为0。

注意: 在Python中,True、False的首字母必须为大写。

2.4 运算符

在Python中,为了实现项目的某一需求或具体功能,需采用运算符和表达式将变量、字符串等关系进行组合并表达出来。Python中的运算符有算术运算符、比较运算符、逻辑运算符、赋值运算符、位运算符、成员运算符(in、not in)、身份运算符(is、is not)。

2.4.1 算术运算符

在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

2.4.2 赋值运算符

在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

2.4.3 比较运算符

在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

2.4.4 逻辑运算符

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 逻辑运算

2.4.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

2.5 数据算法

算法本质上就是解决具体计算问题的实施步骤。可以用“顺序、分支、循环”这3种控制结构实现,如图2-4所示。

图2-4 控制结构

2.5.1 顺序结构

顺序结构比较容易理解。应用举例,代码如下:

    #ch02d005.ipynb
    a = int(input('请输入订单数:'))
    b = a * a
    print('订单数的平方为',b)

运行以上代码,必须先输入a的值才可以得到b的值。假如输入的a值为12,返回的值如下:

    请输入订单数:12
    订单数的平方为144

2.5.2 分支结构

在Python中有if、if-else、if-elif-else这3种常用分支选择语句。

1.if语句

在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
2.else子句

在Python中,if-else-条件表达式适用于“if语句1 else语句2”的应用场景,else子句后面不接条件判断。应用举例,在现有列表中属于华南区域的城市有“广州、深圳、珠海”,如果输入的城市为其中之一,则返回“华南区:广州|深圳|珠海”;如果输入任意城市(例如惠州),则会显示“该城市不在华南区的列表中”,代码如下:

    city=  input('请输入城市名:')
    if city =  = '广州'or city =  = '深圳'or city =  = '珠海':
       print('华南区:',city)
    else:
       print('该城市不在华南区的列表中')

运行以上代码,输入“广州”,返回的值如下:

    请输入城市名:广州
    华南区:广州
3.elif子句

在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
    你输错了!

2.5.3 循环结构

循环是指重复做同一件事情。在Python中主要有for循环与while循环两种,其中for循环为计数循环,同一件事情重复做多少次;while循环为条件循环,只要符合条件就一直循环下去,直到不符合条件时才结束。为了避免出现死循环现象,Python中还提供了break、continue等语句。break用于终止当前循环并结束整个循环,continue用于跳过本次循环的剩余语句并开始新的一轮循环。另外,Python还推出了一个为保持程序结构完整而使用的pass空语句,用于占位。

1.for循环

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个值不符合条件而被筛选移除,返回的值如下:

    ['上海','南京','常州','无锡','苏州']
2.while循环

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
3.推导式

在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['杭州','苏州']]

以上两种方式所实现的功能是等效的。

2.6 迭代器与生成器

2.6.1 迭代器

在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)                     #'苏州'

2.6.2 生成器

在Python中,一边循环一边计算的机制称为生成器(generator)。当运行的数据量过大时,采用生成器方式可极大地节约内存空间。应用举例,将列表推导式中最外层的[]改成(),创建生成器,代码如下:

    g = (pd.read_excel(r'D:\数据源\B文件\华东.xlsx',i)for i in['杭州','苏州'])
    print(g)

运行以上代码,返回的值如下:

    <generator object<genexpr>at 0x00000294BF753660>
1.以next()函数调用生成器

此时可采用迭代方式调用生成器。以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
2.采用for循环调用生成器

代码如下:

    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函数创建生成器,此处不再举例。关于装饰器的相关知识本书不进行介绍。

2.7 函数与方法

2.7.1 内置函数

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

2.7.2 自定义函数

在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数

2.7.3 匿名函数

匿名函数是指没有名字的函数,适用于只需调用一次且代码简短的场合。在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数

2.8 异常处理

异常是指程序在运行过程中所发生的各种错误或不正常。

2.8.1 内置异常

Python中常用的内置预定义的异常见表2-6。

表2-6 Python中常用的内置预定义的异常

2.8.2 异常处理

在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时最后执行的语句。运行以上代码,返回的异常处理提示如下: 6WZU4QHf2I3cTmdlq25eA9MuQ4eB9zyH9hDBXbWlFfKFQvHJOidIQekMPaLLudGO

    你确定字典的键存在华西?
    输入之前先检查!
点击中间区域
呼出菜单
上一章
目录
下一章
×