• 1、Python 基础知识总结


    1、Python 简介

    Python 是一门简单易学的,面向对象的,解释型的脚本语言,也是一种开源的、可移植性强的、可扩展性强的高级编程语言,常用于科学计算与人工智能、WEB 开发、金融、云计算等领域。

      最近几年来,随着大数据和人工智能的流行,因简单易学、面向对象、以及有丰富的第三方库支持,Python 作为一门解释型的语言也流行了起来,甚至一度呈现出碾压 Java 老大哥的趋势。当然,多掌握点技术对自己来说并不算什么坏事,因此我也开始步入了 Python 的世界,希望在以后能更加深入的开阔自己的眼界,毕竟人生苦短,多用多学 Python。

    Python 目前有两个主流的版本方向,Python2.x和Python3.x,鉴于官网2020年对 Python2.x 停止了更新,Python2.7 也正式成为了最后一个Python2.x的版本。对于学习和使用者来说,Python3.x 才是更合理的选择,去官网看看,可下载自己需要的版本,官网链接:https://www.python.org/。

    2、Python 下载、安装与使用

    我选择的是3.8.5版本,选择 windows,x86-64是64位的下载,下载时注意以下文件的区别:

    • web-based installer:需要通过联网完成安装;
    • executable installer:通过可执行文件(*.exe)方式安装(推荐此种类型);
    • embeddable zip file:嵌入式版本,可以集成到其它应用中。

    安装的话,基本是傻瓜式的。如果之前安装过Python其他版本,在系统属性-环境变量中,去掉之前版本的相关环境变量配置;安装过程中,选择自定义安装,最好指定目录安装,勾选安装选项中的“添加环境变量”,“预编译标准库”等选项;

    安装成功后,验证方式有:

    • 打开 CMD,输入python -V 或 python  --version,输出版本信息正常即可;
    • 打开系统属性-环境变量,查看用户变量的 path 是否存在安装目录和scripts目录。

    Python 是一门动态解释型的执行语言,无需编译,定义了后缀为.py的文件,在安装了 Python 环境的机器上去执行,使用 python xx.py 命令即可。

    常用的编辑器,推荐一下:

    CMD:

     自带IDLE:

     其他编辑器

    基础的编辑器可以用:notepad++,当然,还可以使用:

    • Eclipse + PyDev    (插件:https://www.pydev.org/)
    • Sublime Text   ( http://www.sublimetext.com)
    • Atom  (https://atom.io/)
    • Visual Studio Code  (https://code.visualstudio.com/)
    • PyCharm   (https://www.jetbrains.com/pycharm/)

    3、Python 的数据结构

    Python有六种标准数据类型:数字number、字符串str、元组tuple、列表list、集合set、字典dict,而从数据的可变性角度来看,又可分为:不可变的数据类型(数字、字符串、元组) 和 可变的数据类型(列表、集合、字典)。

    <1>、数字类型(Number)

    Python 不像 Java 或 C 语言那样会有整型(有的还分为长整型、短整型等)、浮点型、布尔类型等之分。在 Python 的世界里,整型(int)、浮点型(float)、布尔(bool)、复数(complex)都统称为数字类型,在定义变量时,会根据赋值自行推断类型,不需要指定数据类型

    举例说明:

    1. # 多个变量相同数字类型
    2. x = y = z = 10
    3. # 多个变量不同数字类型
    4. a, b, c, d = 52, 3.14, True, 3+4j

    当然,也可以通过 Python 内置函数 type() 或 isinstance 来获取或判断变量的类型:

    1. # 获取变量的类型
    2. print(type(a), type(b), type(c), type(d))
    3. <class 'int'> <class 'float'> <class 'bool'> <class 'complex'>
    4. # 判断变量额类型
    5. isinstance(a, float) #False
    6. isinstance(b, float) #True

    <2>、字符串类型(String)

    用过 Python2.x 版本写脚本的都知道,字符串是一个很头疼的东西,需要考虑编码,而且使用 print 打印的字符串经常需要转成 unicode才可以输出,这一切在 Python3 做出了重大的改变,因为 Python3 的源码文件默认以 UTF-8 编码,所有字符串默认都是 unicode 字符串。

    字符串需要用单引号或双引号表示,支持转义字符,支持对字符串的一系列基本操作:(比如,字符串截取,重复,连接,格式化,逆序,其他操作符等)

    1. str = 'hello,world!\n'
    2. # 取值,下标从0开始,使用切片格式进行字符串截取操作
    3. print(str[0]) #h
    4. print(str[0:-1]) #hello,world!
    5. print(str[0:len(str)-1]) #hello,world!
    6. print(str[::]) #hello,world!
    7. print(str[0:5:1]) #hello
    8. # 字符串连接
    9. print(str[2] + str[4] + str[9]) #lol
    10. # 字符串重复
    11. print(str[0]*2) #hh
    12. # 字符串格式化 %
    13. #你今年10岁了,你想说的话是:hello
    14. print("你今年%d岁了,你想说的话是:%s"%(10, str[0:5]))
    15. # 字符串逆序
    16. print(str[::-1]) #!dlrow,olleh
    17. # 转义字符如果需要输出,加上r或R即可
    18. print(r'hello,world!\n') #hello,world!\n
    19. # 其他操作符 :in/not in
    20. print('hello' in str) #True

    Python3.6 以上版本增强了字符串的格式化操作,使用f-string完全可以替代用%进行格式化,此外Python3.8+ 还支持表达式的输出,如下:

    1. # Python3.6以上版本
    2. ss = "world"
    3. print(f'hello, {ss}') #hello, world
    4. print(f'{2+3}') #5
    5. # Python3.8+版本
    6. print(f'{2+3=}') #2+3=5

    Python 内置模块也提供了许多操作字符串的 API,常见的 API 有:

    • str(xx):xx转成字符串类型;
    • len(str):计算字符串长度;
    • count(str,start, end):返回指定范围内str在字符串string出现的次数;
    • startswith(str,start, end):在指定范围字符串string内是否存在str开头,存在返回True,否则返回False。endswith(str,start, end)类似。
    • upper():字母转大写,lower():字母转小写。
    • isdigit():字符串是否全部为数字;
    • islower():字符串是否全部小写;
    • spilt():分割字符串;
    • replace(old, new):替换字符串;

     <3>、元组类型(Tuple)

    用(value1,value2,...valueN)形式定义元组,元素可以是任意类型,若一旦被创建将,不能被修改。元组的基本操作也很简单,有切片取值、遍历、删除等。

    1. #定义一个空元组
    2. tup = ()
    3. #定义只有一个元素的元组,不能少了逗号,
    4. tup1 = (2022, )
    5. # 定义包含多种类型元素的元组
    6. tup2 = (2022, 5.20, '中国加油', tup1, [123,'abc'], {"key1":True})
    7. print(type(tup2)) #
    8. # 使用切片操作元组
    9. print(tup2[1:3]) #(5.2, '中国加油')
    10. # 操作符判断
    11. print(2022 in tup2) #False
    12. #遍历元组,依次输出每个元素
    13. for i in tup2:
    14. print(i,)
    15. #删除
    16. del tup1
    17. print(tup1) #报错
    18. Traceback (most recent call last):
    19. File "dataType.py", line 24, in
    20. print(type(tup1))
    21. NameError: name 'tup1' is not defined
    22. #常用函数
    23. s = 'hello'
    24. print(len(tup2)) #6
    25. # print(max(tup2)) #元素相同类型才可使用max、min函数取最值
    26. # print(min(tup2))
    27. print(tuple(s)) #('h', 'e', 'l', 'l', 'o')

    上面的三种类型都有一个共同点,即元素被创建后具有不变性,特别注意元素不能被修改。比如,上面的字符串使用 str[0]='k' 赋值修改元素是不合法的;上面的 tup2[0]=2022 赋值修改元素也是不合法的。

    <4>、列表类型(List)

    列表类型使用[value1,value2,...valueN]形式定义,列表元素存储是有序的且可重复的。与元组定义一样,列表元素可以是任意类型,不同的是,列表元素是可以被修改的,基本操作如下:

    1. #定义两个列表
    2. list1 = [2022]
    3. list2 = [2022, 5.20, '中国加油', list1, [123,'abc'], {"key1":True}]
    4. print(type(list2)) #
    5. print(list2[1:3]) #[5.2, '中国加油']
    6. #遍历列表,依次输出每个元素
    7. for i in list2:
    8. print(i)
    9. #常用函数
    10. s = 'hello'
    11. print(list(s)) #['h', 'e', 'l', 'l', 'o']
    12. print(len(list2)) #6
    13. list2.append(True)
    14. #[2022, 5.2, '中国加油', [2022], [123, 'abc'], {'key1': True}, True]
    15. print(list2)
    16. #移除list1,
    17. list2.remove(list1)
    18. print(list2) #[2022, 5.2, '中国加油', [123, 'abc'], {'key1': True}, True]
    19. list3 = list2.copy()
    20. print(list3) #[2022, 5.2, '中国加油', [123, 'abc'], {'key1': True}, True]
    21. #反转列表
    22. list3.reverse()
    23. print(list3) #[True, {'key1': True}, [123, 'abc'], '中国加油', 5.2, 2022]
    24. #修改元素
    25. list3[0] = False
    26. print(list3) #[False, {'key1': True}, [123, 'abc'], '中国加油', 5.2, 2022]

    <5>、集合类型(Set)

    使用set()函数 或 {value1,value2,...valueN}形式定义集合,集合元素存储是无序的但不能重复。基本操作如下:

    1. # 定义集合,空集合不能使用{}定义,它默认表示的是字典
    2. print(type({})) #
    3. print(set('2022')) #{'2', '0'}
    4. print({2022,5.20,'中国加油'}) #不支持列表、集合、字典
    5. print(type(set2)) #
    6. #遍历,输出:3.14 True abc 123
    7. for i in set2:
    8. print(i, end=' ')
    9. # 定义的集合,要保证元素是相同的
    10. print(set('abcdefg')) #{'e', 'b', 'f', 'g', 'c', 'a', 'd'}
    11. print(set(["a","b","c"])) #{'b', 'c', 'a'}
    12. print(set(("a","b","c"))) #{'b', 'c', 'a'}
    13. #常用函数:元素增删,集合求交并差集等
    14. st=set(("a","b","c"))
    15. st.add('d') #追加元素
    16. print(st) #{'d', 'a', 'c', 'b'}
    17. st1 = st.copy() #拷贝
    18. print(st1.issubset(st)) #True 子集判断
    19. st.pop() #随机移除元素
    20. print(st) #{'d', 'c', 'b'}
    21. print(st1.intersection(st)) #求交集 {'d', 'c', 'b'}
    22. st.remove('c') #指定移除元素,该元素不存在抛异常
    23. print(st) #{'b', 'd'}

    <6>、字典类型(dict)

    使用{key1:value1, key2:value2,...keyN:valueN}形式定义字典,类似于Java的Map,字典元素存储是键值对。基本操作如下:

    1. dicts = {'key1':150,'key2':0.99,1:True,2:2}
    2. # 访问
    3. print(dicts['key1']) #150
    4. print(dicts['1']) #True
    5. #修改
    6. dicts['key2'] = 0.88
    7. print(dicts['key2']) #0.88
    8. #遍历
    9. for d in dicts:
    10. print(d, end=',')
    11. for k,v in dicts.items():
    12. print(k,v)
    13. #删除key
    14. del dicts['key1']
    15. #清空字典
    16. dicts.clear()

    4、Python 流程控制语句

    Python 流程控制语句也很简单,但与 Java 的流程控制语句相比会有许多不同之处,这里流程控制语句主要有条件语句、循环语句等。条件语句指的是if条件语句,Python 是没有swith-case语句的;循环语句的话,指的是for循环和while循环,Python 是没有do-while循环的,不过for循环和while循环都是可以带有else语句的,表示循环条件不满足时执行else语句。

    <1>、条件语句

    1. # if条件语句举例
    2. str = 'hello,world!\n'
    3. if 'h' in str:
    4. print('字符串包含h')
    5. elif 'd' in str:
    6. print('字符串包含d')
    7. else:
    8. pass #不做任何事情,一般用做占位语句

    <2>、循环语句

    while 循环,举例:

    1. a = 5
    2. b = 5
    3. while a < 10:
    4. a = a + 1 #python没有a++或a--运算符
    5. b = b - 1
    6. if b >= 2:
    7. if a == 8:
    8. continue #跳出当前循环进入下一次循环,break则是终止当前循环
    9. print(a, end=' ')
    10. else:
    11. print('\n----------'+str(a))
    12. '''
    13. 6 7
    14. ----------10
    15. '''

    for循环,举例 9*9乘法表:

    1. for i in range(1, 10):
    2. for j in range(1, i+1):
    3. print("{}x{}={}\t".format(j, i, i*j), end='')
    4. print()
    5. '''
    6. 1x1=1
    7. 1x2=2 2x2=4
    8. 1x3=3 2x3=6 3x3=9
    9. 1x4=4 2x4=8 3x4=12 4x4=16
    10. 1x5=5 2x5=10 3x5=15 4x5=20 5x5=25
    11. 1x6=6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36
    12. 1x7=7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49
    13. 1x8=8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64
    14. 1x9=9 2x9=18 3x9=27 4x9=36 5x9=45 6x9=54 7x9=63 8x9=72 9x9=81
    15. '''

    Python 似乎精简了流程控制语句中的许多东西,使用起来更加的简便,而实际上,for 循环经常还会和迭代器、生成器一起使用,这里不再说明,在 Python 进阶知识总结再进行梳理。

    5、Python 函数的概念

    Python 也是一门支持函数式编程的语言,而函数式编程的特点为:支持非纯函数式编程、支持闭包、支持高阶函数、及有限度的支持匿名函数。作为入门的知识点,先梳理下 Python 函数的基本概念。

    Python中的函数定义也很简单,如图所示:

     函数定义:

    • 通过def关键字标识,入参可以无参也可以有参,函数体内可以有返回值也可以没有返回值;
    • 入参的话,写在()内,注意一些特殊传参,比如*args,**kwargs等可变长参数,它们的区别在于:*args传入元组类型,可有多个,**kwargs传入字典类型,也可有多个;
    • 书写函数需要注意行的缩进,注意英文冒号:不要遗漏等;

    参数传递:

    不可变类型参数传递 (如数字、字符串、元组等类型),本质是按值传递。

    1. def fun1(a):
    2. a = 5
    3. return a
    4. a1 = 10
    5. fun1(a1)
    6. print(a1) #10

    可变类型参数传递 (如列表、集合、字典等类型),本质是引用传递。

    1. def fun2(a):
    2. a.append(2022)
    3. values = [True, 3.14, (28,)]
    4. fun2(values)
    5. print(values) #[True, 3.14, (28,), 2022]

    注意:函数也能作为参数进行传递的,这就是高阶函数的特征,后面进阶总结时再详细说明。

    变量作用域:

    模块内存在两种类型的变量,即局部变量和全局变量,通常以变量是否声明在函数体内来区分局部变量全局变量。如果需要在函数体内定义全局变量,需要加上global关键字声明。

    1. a = 0
    2. b = 0
    3. def fun3():
    4. global a #注意不能这样写:global a = 1
    5. a = 1
    6. def fun4():
    7. b = 1
    8. fun3()
    9. print(a) #1
    10. fun4()
    11. print(b) #0

    6、Python 异常处理

    Python 作为一门高级语言,也有着自己的一套异常处理机制。如果代码里没有任何捕获异常处理,Python 会调用默认的异常处理器处理。程序运行前,不管你是否是类型错误(TypeError),还是名称未定义(NameError),还是数组越界(IndexEoor)等其他异常,首先都会进行语法错误(SyntaxError)检查,例如:

    1. x = 0
    2. print('---' + x) #属于类型错误
    3. print(y) #属于名称未定义错误
    4. #属于语法错误
    5. print("我是小小)

    常见的 SyntaxError 有:

    1. #SyntaxError: Missing parentheses in call to 'print'.
    2. print 'hello,world!'
    3. #SyntaxError: invalid syntax ,缺少冒号:
    4. if True
    5. pass
    6. #SyntaxError: invalid syntax ,应该用==判断
    7. x = 0
    8. if x = 0:
    9. pass
    10. #SyntaxError: EOL while scanning string literal
    11. print("我是小小)

    因此,平时需要多注意规范书写,避免低级的语法错误。在 Python 的世界里,运行期间检查到的错误称为异常,大多数的异常都不会被程序去处理,而是以错误的形式展示出来,大多数的异常的名字都以"Error"结尾,和标准的异常命名一样。

    Python 有三种异常处理结构:即 try...except...finally语句块、assert 断言和 with 语句。

    <1>、异常代码块

    Python 也可以主动捕获异常,捕获异常的代码块完整结构及相关用法,如下所示:

    1. try:
    2. #执行代码
    3. execept Exception as e:
    4. #打印异常信息
    5. print(e)
    6. #可以指定具体异常去捕获,也可以写范围更大的异常,如Exception
    7. #该部分可省略,异常时执行的代码,会抛出异常信息
    8. raise e
    9. execept Exception1 as e1:
    10. #可以抛出多个异常
    11. print(e)
    12. else:
    13. #该部分可省略,未发生异常时执行的代码
    14. finally:
    15. #该部分可省略,无论是否发生异常,一定会执行(除非程序退出/中断)

    <2>、assert断言

    断言,是一种判断表达式,当表达式结果为False时会触发异常,完整的断言语法为:

    1. assert expression [,args]
    2. # 等价于:
    3. if not expression:
    4. raise AssertionError(args)

    举例说明:

    1. assert 1==2 , '你两不合适,没有相等!'
    2. #运行结果
    3. D:\XXX\demo>python a.py
    4. Traceback (most recent call last):
    5. File "a.py", line 3, in
    6. assert 1==2 , '你两不合适,没有相等!'
    7. AssertionError: 你两不合适,没有相等!

    <3>、with语句块

    像 Java 语言异常处理时,使用异常语句块书写的代码显得特别的臃肿,然而 Python 异常处理的话,除了可以使用try...except...finally语句块外,还可以使用with语法,如果对比二者的代码量,一定会为 Python 代码的短小而精简震撼,以使用游标查询数据来举例说明:

    try...except...finally:

    1. try:
    2. conn = getconnection()
    3. sql = 'select * from t'
    4. cursor = conn.cursor()
    5. cursor.execute(sql)
    6. print(cursor.fecthall())
    7. except Exception as e:
    8. print(e)
    9. cursor.rollback() #异常时回滚
    10. raise e #捕获异常
    11. finally:
    12. #释放资源
    13. cursor.close()
    14. conn.close()

    with...as语句:

    1. with getconnection().cursor() as cursor:
    2. cursor.execute('select * from t')
    3. print(cursor.fecthall())

    with 语句强大之处在于,不用我们再去手动捕获异常,不用再去一个个close资源连接,将这一系列的工作都交给了 Python 内部去处理。with 语句在操作文件读写,操作数据库等方面很实用,推荐使用。

    7、Python 文件读写操作

    os 模块是 Python 的内置模块,它提供了很多的 API 方法用来操作目录和文件,我们可以在 Python 安装目录找到 doc,里面可以找到 os 模块的文档说明,os 模块的主要用途如下:

    • 要进行文件读写操作的话,使用open()函数;
    • 要操作文件属性及路径的话,使用os.path模块;
    • 要读取命令行中文件的话,使用fileinput模块;
    • 要操作临时目录或文件的话,使用tempfile模块;
    • 更高级的目录或文件操作,使用shutil模块。

    这里,重点说明下文件的读写操作。在计算机的世界里,文件后缀的格式多不胜数,我们只需要知道常见的文件格式就行,比如:.txt、.log、.json、.csv、.xls/.xlsx、.doc/.docx、.ppt、.xml、.yml等。

    <1>、文件读写API

    读写文件的方法为open(),通常有两种写法:

    1. #默认, mode='r'
    2. f = open(filename)
    3. #指定
    4. f = open(filename, mode [,encoding='utf-8' ,...])

    模式 mode 参数有:

    文件读取操作有关的方法有:

    • f.read():读取文件内容;
    • f.readline(size):读取一行,size表示读取该行多少个字符;
    • f.readlines():读取文件所有的行,以列表的形式返回;
    • f.tell():返回文件当前的位置;
    • f.seek(offset[, whence]):移动文件读取指针到指定位置,offset:开始的偏移量,whence:0 从文件开头开始算起,1 从当前位置开始算起,2 从文件末尾算起;
    • f.close():关闭文件,释放资源。

    文件写入操作有关的方法有:

    • f.write(str):将字符串写入文件,返回的是写入的字符长度;
    • f.writelines(sequence):向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符;
    • f.flush():刷新文件内部缓冲,直接把内部缓冲区数据立刻写入文件, 而不是被动等待输出缓冲区写入。

    普通的 open() 操作,无论读写,在最后都要使用 close() 方法手动关闭连接,这一点不要忽略了。而如果使用的是 with open() 语法形式,则不需要手动去关闭,举例说明:

    1. #写入
    2. with open("D:\\XXX\\test.txt", 'a+', encoding='utf-8') as wf:
    3. tell = wf.tell();
    4. wf.write("\n当前位置:杭州市西湖区留下街道梦溪街")
    5. tell2 = wf.tell();
    6. if tell2 > tell:
    7. print("写入成功!")
    8. if wf.closed == False:
    9. print("--------测试---------" )
    10. wf.close()
    11. print("文件是否关闭:" , wf.closed)
    12. #读取
    13. with open('D:\\XXX\\test.txt','r',encoding='utf-8') as rf:
    14. context = rf.readlines()
    15. if rf.closed == False:
    16. print("-------测试----------" )
    17. rf.close()
    18. print("文件是否关闭:" , rf.closed)
    19. print("文件文本内容:" , context)

    执行结果:

     <2>、读写.txt/.log文件

    使用上面的有关的API即可实现,比较简单。

    <3>、读写.json文件

    1. 第一步:导入json模块;
    2. 第二步:借助该模块dump()实现写入文件功能, load()实现读取文件功能;
    3. 更多API可以参考:https://docs.python.org/zh-cn/3/library/json.html 。

    举例说明:

    1. import json
    2. dicts = {'a':100, 'b':200, 'c':300}
    3. with open('D:\\XXX\\response.json', 'a', encoding='utf-8') as wf:
    4. json_str = json.dump(dicts, wf)
    5. print(json_str)
    6. print(type(json_str))
    7. with open('D:\\XXX\\response.json', 'r', encoding='utf-8') as rf:
    8. json_obj = json.load(rf)
    9. print(json_obj)
    10. print(type(json_obj))

    执行结果:

     <4>、读写csv文件/excel文件

    csv文件已在上面的演示中用过了,不再举例。excel文件与csv文件看上去很相似,但依赖的模块和操作却不一样,excel文件的后缀是.xls 或 .xlsx,有许多模块支持 excel 的读写操作,比如:

    • openpyxl:A Python library to read/write Excel 2010 xlsx/xlsm files;
    • xlrd + xlwt + xlutils:三个模块搭配使用,对excel读写和复制等操作。

    这里,使用 openpyxl 模块,使用pip命令下载:

    pip install openpyxl

    举例说明:

    1. from openpyxl import load_workbook,Workbook
    2. #write excel
    3. excelName = 'D:\\XXX\\test-write-0605.xlsx'
    4. lwb = Workbook()
    5. print("开始写入......")
    6. #激活sheet,默认sheet,以后新增sheet1,sheet2......
    7. ws = lwb.active
    8. tableHeader = ['姓名','年龄','身份证号码','现居住地','原籍所在地','联系电话']
    9. for c in range(len(tableHeader)):
    10. col = c + 1
    11. ws.cell(row=1, column=col).value = tableHeader[c]
    12. tableBody = [['魏详详','27','341226199203071600','杭州市','颍上县','15077925650'],['魏详详1','28','341226199203171604','杭州市','颍上县江口镇','15077925655']]
    13. for r in range(len(tableBody)):
    14. ws.append(tableBody[r])
    15. lwb.save(excelName)
    16. print("写入完成!!!")
    17. #read excel
    18. wb = load_workbook('D:\\XXX\\20210605.xlsx')
    19. print("开始读取......")
    20. #获取所有的sheet
    21. #sheetList = wb.get_sheet_names()
    22. sheetList = wb.sheetnames
    23. print("sheetList: " + str(sheetList))
    24. #获取第一个sheet
    25. #currentSheet = wb.get_sheet_by_name(sheetList[0])
    26. currentSheet = wb[sheetList[0]]
    27. print("title: " + str(currentSheet.title))#sheet名称
    28. print("max_row: " + str(currentSheet.max_row))#最大行数
    29. print("max_column: " + str(currentSheet.max_column))#最大列数
    30. #读取第一个sheet, 逐行按单元格读取
    31. lineList=[]
    32. for i in range(2, currentSheet.max_row+1):
    33. for j in range(1, currentSheet.max_column+1):
    34. cellValue = currentSheet.cell(row=i, column=j).value
    35. lineList.append(cellValue)
    36. print("读取完成!!!")
    37. print("结果:" + str(lineList))

    执行结果:

     日志:

    需要注意,读写excel时,单元格的坐标位置起始值是(1,1),load_workbook用于写excel、Workbook用于读取excel。更多API参考:https://openpyxl.readthedocs.io/en/stable/index.html#。

    <5>、读写Word文件

    Word 文件的后缀有.doc 和 .docx 格式,以下模块支持 word 文档的读写:

    • python-docx:只支持.docx 格式,但可以将 .doc 转成 .docx 格式,从而间接支持 .doc 格式;(API参考:https://python-docx.readthedocs.io/en/latest/index.html)
    • win32com:调用系统的word功能,可以同时支持.doc 和 .docx 格式。

    这里,使用 wun32com模块,使用pip命令下载:

    pip install pywin32

    我们能如此方便的调用 Word,得益于其底层的 COM(组件对象模型)可以被任意语言调用,操作 word 时需要知道以下对象:

    • Application:表示Word应用。包含了菜单栏、工具栏、命令以及所有文档等;
    • Documents:表示文档,可有多个。有打开Open()、创建Add()等API;
    • Selection:表示当前窗口的光标焦点或选择范围。有输入TypeText()、复制Copy()、粘贴Paste()、删除Delete()、全选WholeStory() 、左移MoveLeft()、右移MoveRight(start, end)等API;
    • Range:表示连续区域,用于区分文档不同位置,Range(0, 0)表示开始位置,Range()表示文末位置。
    • 对 Selection 和 Range 也可以设置字体 Font、设置段落 ParagraphFormat 、设置 PageSetup、设置样式 Styles等。

    举例1创建Word文档,并转储到txt文件中

    1. import win32com
    2. import win32com.client
    3. #wordPath = 'D:\\XXX\\SpringCloud学习笔记.docx'
    4. txtPath = 'D:\\XXX\\转储创建的word文档1.txt'
    5. app = win32com.client.Dispatch('Word.Application')
    6. #显示word
    7. app.Visible = True
    8. #创建word,并插入文字
    9. doc = app.Documents.Add()
    10. contxt1 = doc.Range(0, 0)
    11. contxt1.InsertBefore('Hello word\n')
    12. contxt2 = doc.Range(10, 11)
    13. contxt2.InsertAfter('我是魏详详\n')
    14. contxt3 = doc.Range()
    15. contxt3.InsertAfter('\n updatetime: 20210605')
    16. #转储到其他文件:2为txt,
    17. doc.SaveAs(txtPath, 2)
    18. print("文件转储成功!!!")
    19. #关闭word
    20. doc.Close()
    21. app.Quit()

    转储txt内容:

     举例2读取Word文档,并转储到txt文件中

    1. import win32com
    2. import win32com.client
    3. wordPath = 'D:\\XXX\\SpringCloud学习笔记.docx'
    4. txtPath = 'D:\\XXX\\SpringCloud学习笔记.txt'
    5. #打开office
    6. app = win32com.client.Dispatch('Word.Application')
    7. #打开word
    8. word = app.Documents.Open(wordPath)
    9. #打印word内容
    10. '''
    11. for i in word.Paragraphs:
    12. line = i.Range.Text
    13. print(line)
    14. '''
    15. #转储到其他文件:2为txt,
    16. word.SaveAs(txtPath, 2)
    17. print("文件转储成功!!!")
    18. #关闭word
    19. word.Close()
    20. #关闭office
    21. app.Quit()

    <6>、读写其他文件

    文件类型那么多,不可能面面俱到的去演示读写操作的,从上面的Demo可以看到通用的思路如下:

    • 要先明确是否需要导入模块,可以自行百度或去pip官网进行依赖查询;
    • 尽量找到详细可参考的文档读写操作API,并亲测该方法的功能后再使用;

    8、Python 模块

    Python 流行而强大之处在于支持丰富的第三方库,这为实现很多的拓展功能提供的可能。通常使用 pip 命令安装需要的第三方模块,但使用 pip 命令之前,请确保机器上安装了 Python 环境,并在环境变量中配置了 Scripts 目录。

    pip 支持的第三方模块,可以去官网查询相关依赖:https://pypi.org/ 。当然,有必要了解下 pip 的相关命令:

    • pip list:查看已安装的第三方模块
    • pip install模块名:安装第三方模块
    • pip show --files 模块名:查看是否已安装的模块信息
    • pip list --outdated:检查哪些模块名需要更新升级
    • pip install --upgrade 模块名:更新升级第三方模块
    • pip uninstall 模块名:卸载第三方模块
    • pip --help:帮助命令

    以图像处理模块(Pillow)为例,演示:

    第一步,先下载该模块:

    pip install Pillow

     第二步,查看该模块的详细信息:

    pip show --files Pillow

    之后便可以愉快的使用 Pillow 模块提供的API了~~

    这里需要注意区分:Python 自带模块与第三方模块?

    • Python自身带有内置的模块供开发者使用,在安装的时候勾选了文档的话,可以通过提供的文档查看有哪些内置模块:http://localhost:57952/ 。
    • 第三方模块的话,需要额外去下载才能被使用,可以先查询是否存在再下载或者升级。

    不论是自带模块,还是第三方提供的模块,导入的方式有下面几种

    1. #用法1:分行导入模块
    2. import module1
    3. import module2
    4. import moduleN
    5. #用法2:一行导入模块
    6. import module1 [,module2 ,module3, ...,moduleN]
    7. #用法3:可以导入模块中所有内容(除了私有的变量/函数)
    8. import module from name1[,name2 ,name3, ...,nameN]
    9. #用法4:可以导入模块中所有内容(除了私有的变量/函数),不推荐使用*
    10. import module from *
    11. #用法5:导入模块中需要的内容
    12. import module from name1,name2

    值得注意的是用法4,可以使用但不推荐。使用*导入模块中所有的内容,这里会把私有变量和私有函数除外的所有变量/函数/类等导入,容易造成混乱,也可能会覆盖当前模块的同名变量或同名函数,所以要注意这类规范。

    Python 模块很简单,深入起来也有点东西,下面是我学习过程中遇到的问题及思考过程,也顺便记录下。

    思考一个问题,在一个模块中,我们使用了其他很多的模块也存在的变量或函数,为什么在这个模块中能正常使用而不发生冲突呢?

    这是因为 Python 中的每个模块都拥有各自独立的符号表,每个模块中的所有函数都会在符号表中被当做全局符号使用,每个模块间的全局变量相互是隔离的,因此能正常使用。

    再思考一个问题,比如当前模块A要引入模块B或模块B中指定的变量或函数,在第一次运行程序时,模块B中的变量或函数会放到模块A中的符号表中,那我怎么保证模块B的某段代码块不会再模块A中被执行呢?

    这个问题的答案发现是我之前疑惑已久的问题,那就是为什么类的模块里经常要写以下代码呢:

    1. if __name__=='__main__':
    2. pass

    其实,__name__属性是模块的私有属性,通过 __name__=='__main__': 能控制某些代码块只在本模块内会被使用,不会在引入该模块的模块里使用!

    接着,思考更复杂的一些问题。假设存在以下目录结构:(src下有两个模块mod1.py和mod2.py、两个包p1和p2,而p1包和p2包又存在各自的模块,p1包下为mod.py和mod1.py,p2包下为mod.py和mod2.py)

    <1>、导入平级目录的模块

    在src目录下的mod1.py中导入src下的mod2.py(同级目录的模块引入),直接按模块名称导入即可。如果当前模块mod1存在与模块mod2的同名变量或同名函数时,使用导入模块名.变量 或 导入模块名.函数区分

    mod2.py :

    1. a = 3.14
    2. def m1():
    3. print('-----mod2模块的m1()----->'+str(a))
    4. def m2():
    5. print('-----mod2模块的m2()-----')
    6. if __name__=='__main__':
    7. print('不会输出到其他模块!!!')

    mod1.py :(测试)

    1. import mod2
    2. a = 3.14
    3. def m1():
    4. print('-----mod1模块的m1()----->'+str(a))
    5. def m2():
    6. print('-----mod1模块的m2()-----')
    7. print(a)
    8. print(mod2.a)
    9. print(m1())
    10. print(mod2.m1())
    11. print(m2())
    12. print(mod2.m2())

    结果:

     <2>、导入下级子目录模块

    在src目录下的mod1.py中导入p1包下的mod.py(父包引入子包),这里使用包名.模块名导入即可,包可以理解为Python管理模块命名空间的方式,最好在该包下加入__init__.py模块标识如果当前模块mod1存在与模块mod的同名变量或同名函数时,使用导入包名.模块名.变量 或 导入包名.模块名.函数区分。

     p1包下的mod.py

    1. pi = 3.14
    2. def m1():
    3. print('-----p1包mod模块的m1()----->'+str(pi))
    4. if __name__=='__main__':
    5. print('测试1:不会输出到其他模块!!!')
    6. print('测试2:会输出到其他模块!!!')

     mod1.py :(测试)

    1. import p1.mod as pmod
    2. a = 3.14
    3. def m1():
    4. print('-----mod1模块的m1()----->'+str(a))
    5. print(m1())
    6. print(pmod.m1())

    结果:

     <3>、导入上级父目录模块

    在p2包下的mod2.py中导入src目录下的mod2.py(子包引入父包),使用 import src.mod2 as smod2 方式会报错:ModuleNotFoundError: No module named 'src'  。

    p2包下的mod2.py:(测试,报错!!!)

    1. import src.mod2 as smod2
    2. a = 3.14
    3. def m1():
    4. print('-----p2包下mod2模块的m1()----->'+str(a))
    5. print(a)
    6. print(smod2.a)
    7. print(m1())
    8. print(smod2.m1())

    这里,我接着测试了p2包的mod2模块导入p1包的mod模块(兄弟包模块引入),报错: ModuleNotFoundError: No module named 'p1' 。

    额,这结果太让人疑惑了,我在想上面这两报错种情况的出现,应该是与Python搜索模块的机制有关系的,那有必要搞清楚Python搜索模块的顺序

    • 优先搜索内置模块(上面的自定义模块不属于内置模块)
    • 接着搜索sys.path(打印出来sys.path都有哪些东西?)
    1. #当前所在位置p2目录
    2. import sys
    3. print(sys.path) #返回一个列表
    4. '''
    5. ['D:\\XXX\\src\\p2', #自定义模块在的目录
    6. 'D:\\Python38\\python38.zip', #标准库的目录
    7. 'D:\\Python38\\DLLs',
    8. 'D:\\Python38\\lib', 'D:\\Python38',
    9. 'D:\\Python38\\lib\\site-packages', #第三方扩展模块的目录
    10. 'D:\\Python38\\lib\\site-packages\\win32',
    11. 'D:\\Python38\\lib\\site-packages\\win32\\lib',
    12. 'D:\\Python38\\lib\\site-packages\\Pythonwin']
    13. '''

    可以看到,列表返回的搜索顺序为:

    • 自定义模块所在的根目录,这里是p2包;
    • 标准库的目录;
    • 最后是site-packages,即第三方扩展模块的目录;

    由此可以清晰的看到,对于自定义模块所在的包会成为根目录,而根目录是没有父目录或者兄弟目录的,这就解释了为什么子包引入父包、兄弟包之间引用会报错找不到父包找不到兄弟包。因此,平时引用自定义模块时应当避免这些情况的发生,做到规范引入模块!!!

    最后呢,值得关注下__init__.py模块的作用,前面提及到该模块是为了标识当前目录是一个包,能够避免影响到搜索路径中的有效模块,这也是一种约定俗成的规范吧。有时候该模块可能会定义一个__all__的私有变量,那么它是干嘛用的呢?

    比如有一个场景:使用from p2.mod import * ,预期的结果是将自定义p2包下mod.py模块的所有的非私有变量/函数全部引入到了当前模块里,假如内置模块或标准库也存在p2包及包下的mod.py模块,那么进行搜索路径模块时可能就无法区分是否来自于自定义模块了。

    此时,通过自定义包p1下的__init__.py模块维护一个__all__变量,里面存放着该包下的所有模块列表,当搜索路径模块时根据它就能唯一确定模块的位置了。__all__变量定义如下:

    __all__ = ['mod.py', 'mod1.py']

    当该包发生更新时(如修改模块名称,或新增模块名),记得维护下这个变量的列表内容!!!

    模块很简单,深入起来也有点东西,通过深入了解后,总结一下几个值得注意的规范:

    1. 慎用 import module from * 方式导入;
    2. 引入包的模块时,避免引入它的父包和兄弟包下的模块;
    3. 自定义包下最好定义一个__init__.py模块,该模块里最好定义一个__all__变量,当该包更新时及时维护__all__变量;
    4. Python搜索路径模块的大致顺序为:内置模块 > 自定义模块 >环境变量目录下的模块 > 标准库目录下的模块 > 第三方扩展目录下的模块等,尽量不要在除了自定义模块目录外的其他目录下定义包或模块。

    Python 基础知识的总结,就到这~

  • 相关阅读:
    HTML期末大作业:基于HTML+CSS+JavaScript新能源汽车资讯门户网站
    Three outline物体边界线条实例
    【VS2019 Qt5 VTK9.2】临时解决配置相关问题的简单方法
    【试题030】C语言之关系表达式例题
    智能合约通过getAmountsOut方法获取最近币对价格
    内核驱动mmap Handler利用技术(二)
    指针和字符数组笔试题及其解析(第三组)
    A-Level Business Studies 真题及解析(2)
    【12】Head First Java 学习笔记
    【智能家居】
  • 原文地址:https://blog.csdn.net/qq_29119581/article/details/126673475