一、模块

1. 模块初识

模块定义:模块(module),通常也被称为库(lib,library),是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。

如:os 是系统相关的模块;file是文件操作相关的模块

模块类别:

    • 自定义模块

    • 内置模块

    • 开源模块

常见Python内置模块解释
名称 功能介绍 详细解释
os 操作系统相关 os.path — Common pathname manipulations
sys 系统相关 sys — System-specific parameters and functions
urlib 网络相关 urllib — Open arbitrary resources by URL
re 正则表达式 re — Regular expression operations
json 处理JSON字符串 json — JSON encoder and decoder

2.模块导入

Python之所以应用越来越广泛,在一定程度上也依赖于其为程序员提供了大量的模块以供使用,如果想要使用模块,则需要导入。导入模块有一下几种方法:

1 import module
2 from module.xx.xx import xx
3 from module.xx.xx import xx as rename
4 from module.xx.xx import *

导入模块其实就是告诉Python解释器去解释那个py文件:

  • 导入一个py文件,解释器解释该py文件
  • 导入一个包,解释器解释该包下的 __init__.py 文件
import sys

for i in sys.path:
print(i) ==============================================
E:\s15\day6 #程序所在目录路径
E:\s15 #程序所在目录上级目录路径
D:\Python\python35.zip #python解释器zip
D:\Python\DLLs #pythonDLLs文件路径
D:\Python\lib #python自带lib库路径
D:\Python #python安装目录路径
D:\Python\lib\site-packages #python第三方库路径

sys.path路径列表没有你想要的路径,可以通过os.patch.abspatch()添加:

import sys
import os pre_path = os.path.abspath('C:\windows')
sys.path.append(pre_path)

3.Json和Pickle

把一个内存对象转换成字符串形式,就叫做序列化;把一个字符串转换成对应的内存对象,就叫做反序列化。序列化的作用就是持久化内存对象。

用于序列化的两个模块:

  • json,用于字符串 和 python数据类型间进行转换
  • pickle,用于python特有的类型 和 python的数据类型间进行转换

Json模块提供了四个功能:dumps、dump、loads、load

 1 import json,os,sys
2
3 data = {'name':'lain',
4 'age':22,
5 'career':'ops'}
6 '''序列化'''
7 f = open('data.txt','w',encoding='UTF-8')
8 #json.dump(data,f)
9 f.write(json.dumps(data))
10
11
12 '''反序列化'''
13 f = open('data.txt',encoding='utf-8')
14 data = json.loads(f.read())
15 #data = json.load(f)
16 print(data['name'])

pickle模块提供了四个功能:dumps、dump、loads、load

 1 import pickle
2
3 data = {'name':'lain',
4 'age':'24',
5 'jobs':'CA',
6 }
7
8 '''序列化'''
9 f = open('data.pkl','wb')
10 f.write(pickle.dumps(data))
11
12 '''反序列化'''
13 f = open('data.pkl','rb')
14 data = pickle.loads(f.read())
15 print(data)

Json无法序列化函数,pickle可以序列化函数(反序列化时需要定义调用函数),Json只能序列化和反序列化普通数据类型,pickle只属于python,所以支持一切python数据类型。

4.Time&Datetime

import time
print(time.altzone/3600) #时区差
print(time.asctime()) #打印时间
print(time.localtime((time.time()+3600*8))) #本地时间对象,可以修改时间
print(time.time()) #1970年到现在,时间戳
print(time.gmtime(time.time()+3600*8)) #UTC时间对象,可以修改时间
print(time.ctime()) #返回当前时间
###########字符串转时间戳###########
print(time.strptime("2016-11-30 19:46","%Y-%m-%d %H:%M")) #字符串转时间对象,只读
print(time.mktime(time.strptime("2016-11-30 19:46","%Y-%m-%d %H:%M"))) #时间对象转成时间戳
###########时间戳转字符串###########
print(time.strftime("%Y-%m-%d %H-%M",time.strptime("2016-11-30 19:46","%Y-%m-%d %H:%M")))
print(time.asctime()) #返回当前时间格式
=============================================
import datetime
###############时间运算###############
print(datetime.datetime.now()) #打印当前本地时间
print(datetime.timedelta(days=3)) #设置要加减的时间
print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间+3天
print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间-3天
print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间+3小时
print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间+30分
datetime.timedelta('后面添加days=0, seconds=0, microseconds=0,milliseconds=0, minutes=0, hours=0, weeks=0') ###############时间替换###############
t = datetime.datetime.now()
print(t.replace(month=1,day=2))

5.Random随机数

import random,string

print(random.random())  #随机打印小数
print(random.randint(1,10)) #包含起始数
print(random.randint(1,10)) #不包含末尾
print(random.sample(range(10),5)) #从1~10中,随机取5个数 ###############随机生成验证码###############
print(string.ascii_letters) #assic码表字母大小写
print(string.digits) #只有数字
print(string.hexdigits) #数字加字母大小写 #简单方式
str_source = string.ascii_letters + string.digits + string.hexdigits
print(random.sample(str_source,12))
print(''.join(random.sample(str_source,12))) #复杂方式
import random
checkcode = ''
for i in range(12):
current = random.randrange(0,12)
if current != i:
temp = chr(random.randint(65,90))
else:
temp = random.randint(0,9)
checkcode += str(temp)
print(checkcode)

6.OS模块

os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
os.curdir 返回当前目录: ('.')
os.pardir 获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2') 可生成多层递归目录
os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() 删除一个文件
os.rename("oldname","newname") 重命名文件/目录
os.stat('path/filename') 获取文件/目录信息
os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep 输出用于分割文件路径的字符串
os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command") 运行shell命令,直接显示
os.environ 获取系统环境变量
os.path.abspath(path) 返回path规范化的绝对路径
os.path.split(path) 将path分割成目录和文件名二元组返回
os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间

7.Sys模块

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0)
sys.version 获取Python解释程序的版本信息
sys.maxint 最大的Int值
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
sys.stdout.write('please:')
val = sys.stdin.readline()[:-1]

8.Shutil模块

对高级的文件、文件夹、压缩包处理模块

import shutil

#################copyfileobj#################
f1 = open('time.py',encoding='utf-8')
f2 = open('time_new.py','w',encoding='UTF-8')
shutil.copyfileobj(f1,f2) #################copy#################
shutil.copy('time.py','time_bak.py') #改变文件属性
shutil.copyfile('time.py','time_bak.py') #不改变文件属性
shutil.copy2('time.py','time_bak.py') #及拷贝权限,又拷贝状态
shutil.copytree('time.py','time_bak.py') #递归拷贝目录
shutil.rmtree('time.py') #递归删除
shutil.make_archive('time.py','time_bak.py') #存档
shutil.make_archive('day6','gztar',root_dir='time_new.py') #压缩存档
##################################
shutil.make_archive(base_name, format,...) 创建压缩包并返回文件路径,例如:zip、tar base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如:www =>保存至当前路径
如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
root_dir: 要压缩的文件夹路径(默认当前目录)
owner: 用户,默认当前用户
group: 组,默认当前组
logger: 用于记录日志,通常是logging.Logger对象
################################### import zipfile,tarfile #################zip压缩#################
z = zipfile.ZipFile('laxi.zip', 'w')
z.write('a.log')
z.write('data.data')
z.close() #################zip解压#################
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall()
z.close() #################tar压缩#################
tar = tarfile.open('your.tar','w')
tar.add('/Users/wupeiqi/PycharmProjects/bbs2.zip', arcname='bbs2.zip')
tar.add('/Users/wupeiqi/PycharmProjects/cmdb.zip', arcname='cmdb.zip')
tar.close() #################tar解压#################
tar = tarfile.open('your.tar','r')
tar.extractall() # 可设置解压地址
tar.close()

9.Shelve模块

shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式

#################存入#################
import shelve d = shelve.open('shelve_list') def stu_data(name,age):
print('register stu',name,age) name = ['alex','rain','lain']
info = {'name':'alex','age':33} d['test'] = name
d['info'] = info
d['func'] = stu_data #################取出#################
import shelve f = shelve.open('shelve_list')
def stu_data(name,age):
print('stu',name,age) print(f['test'])
print(f['info'])
print(f['func']('test',30))

10.XML处理模块

 1 <?xml version="1.0"?>
2 <data>
3 <country name="Liechtenstein">
4 <rank updated="yes">12</rank>
5 <year>2008</year>
6 <gdppc>141100</gdppc>
7 <neighbor name="Austria" direction="E"/>
8 <neighbor name="Switzerland" direction="W"/>
9 </country>
10 <country name="Singapore">
11 <rank updated="yes">52</rank>
12 <year>2011</year>
13 <gdppc>59900</gdppc>
14 <neighbor name="Malaysia" direction="N"/>
15 </country>
16 <country name="Panama">
17 <rank updated="yes">32</rank>
18 <year>2011</year>
19 <gdppc>13600</gdppc>
20 <neighbor name="Costa Rica" direction="W"/>
21 <neighbor name="Colombia" direction="E"/>
22 </country>
23 </data>
 1 #查询test.xml内容
2 import xml.etree.ElementTree as ET
3
4 tree = ET.parse('test.xml')
5 root = tree.getroot()
6 #print(root.tag) #最外层根节点
7
8 for child in root:
9 #print(child) #打印country节点
10 for i in child:
11 print(i) #打印country节点下内容
12
13 for node in root.iter('year'):
14 print(node) #打印所有year节点
15
16 #删除test.xml内容
17 for country in root.findall('country'):
18 #print(country)
19 rank = int(country.find('rank').text)
20 if rank > 50:
21 root.remove(country)
22 tree.write('test_back.xml')
23
24 #修改test.xml内容
25 for node in root.iter('gdppc'):
26 new_year = int(node.text)+10 #获取gdppc值
27 node.text = str(new_year)
28 tree.write('test_update.xml')
29
30 #创建xml
31 new_xml = ET.Element("NameList")
32 name = ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"})
33 age = ET.SubElement(name, "age", attrib={"checked": "no"})
34 sex = ET.SubElement(name, "sex")
35 sex.text = '33'
36 name2 = ET.SubElement(new_xml, "name", attrib={"enrolled": "no"})
37 age = ET.SubElement(name2, "age")
38 age.text = '19'
39
40 et = ET.ElementTree(new_xml) # 生成文档对象
41 et.write("test_grant.xml", encoding="utf-8", xml_declaration=True)
42
43 ET.dump(new_xml) # 打印生成的格式

11.ConfigParser模块

import configparser

#生成配置文件
config = configparser.ConfigParser()
config['DEFAULT'] = {'ServerAliveInterval':'33',
'Compression':'yes',
'CompressionLevel':'8',
'ForwardX11':'yes',
} config['bitbucket.org'] = {}
config['bitbucket.org']['User'] = 'shanpao' config['lain.com.cn'] = {}
topsecret = config['lain.com.cn']
topsecret['Host Port'] = '11111'
topsecret['ForwardX11'] = 'no'
topsecret['Log Dir'] = '/usr/local/opt/lain.log' with open('examplie.ini','w',encoding='utf-8') as i :
config.write(i) #查询配置文件
print(config.sections())
config.read('examplie.ini')
print(config.sections())

12.Hashlib

import  hashlib

#md5校验
m = hashlib.md5()
m.update(b"hvFbbl5uddUHgnE")
print(m.hexdigest()) #sha1
h1 = hashlib.sha1()
h1.update(b'zouliang')
print(h1.hexdigest()) #sha224
h2 = hashlib.sha224()
h2.update(b'zouliang')
print(h2.hexdigest()) #sha256
h25 = hashlib.sha256()
h25.update(b'zouliang')
print(h25.hexdigest()) #sha384
h3 = hashlib.sha256()
h3.update(b'zouliang')
print(h3.hexdigest()) #sha512
h5 = hashlib.sha512()
h5.update(b'zouliang')
print(h5.hexdigest()) #hmac加盐,网络上消息速度传输
import hmac
h = hmac.new(b'zouliang',b'lain') #key,msg
print(h.hexdigest())

13.Logging

import logging

#默认级别输出warning以上
logging.debug('test debug!!!')
logging.info('test info!!!')
logging.warning('test warning!!!')
logging.error('test error!!!')
logging.critical('test critical!!!') #指定日志级别,输出到文件
logging.basicConfig(filename='loging.log',level=logging.DEBUG)
logging.debug('test debug!!!')
logging.info('test info!!!')
logging.warning('test warning!!!')
logging.error('test error!!!')
logging.critical('test critical!!!') #打印时间戳,输出日志
logging.basicConfig(format='%(asctime)s %(message)s',datefmt='%m %d %Y %I:%M:%S %p')
logging.basicConfig(filename='loging.log',level=logging.DEBUG,format='%(asctime)s %(message)s',datefmt='%m %d %Y %I:%M:%S %p')
logging.warning('this event was logged.') #Logger
log = logging.getLogger('TEST-LOG-Logging')
log.setLevel(logging.DEBUG) sh = logging.StreamHandler()
sh.setLevel(logging.WARNING) fh = logging.FileHandler('loging_test.log',encoding='utf-8')
fh.setLevel(logging.ERROR) fh_fortmatter = logging.Formatter('%(asctime)s:%(message)s:%(name)s')
sh_fortmatter = logging.Formatter('%(asctime)s:%(funcName)s')

%(name)s

Logger的名字

%(levelno)s

数字形式的日志级别

%(levelname)s

文本形式的日志级别

%(pathname)s

调用日志输出函数的模块的完整路径名,可能没有

%(filename)s

调用日志输出函数的模块的文件名

%(module)s

调用日志输出函数的模块名

%(funcName)s

调用日志输出函数的函数名

%(lineno)d

调用日志输出函数的语句所在的代码行

%(created)f

当前时间,用UNIX标准的表示时间的浮 点数表示

%(relativeCreated)d

输出日志信息时的,自Logger创建以 来的毫秒数

%(asctime)s

字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒

%(thread)d

线程ID。可能没有

%(threadName)s

线程名。可能没有

%(process)d

进程ID。可能没有

%(message)s

用户输出的消息

14.Re模块(python正则表达式)

'.'     默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
'$' 匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以
'*' 匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac") 结果为['abb', 'ab', 'a']
'+' 匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
'?' 匹配前一个字符1次或0次
'{m}' 匹配前一个字符m次
'{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
'|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
'(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c '\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的
'\Z' 匹配字符结尾,同$
'\d' 匹配数字0-9
'\D' 匹配非数字
'\w' 匹配[A-Za-z0-9]
'\W' 匹配非[A-Za-z0-9]
's' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t' '(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '1993'}

常用匹配语法

1 re.match 从头开始匹配
2 re.search 匹配包含
3 re.findall 把所有匹配到的字符放到以列表中的元素返回
4 re.splitall 以匹配到的字符当做列表分隔符
5 re.sub 匹配字符并替换

特殊用法

re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
M(MULTILINE): 多行模式,改变'^'和'$'的行为(参见上图)
S(DOTALL): 点任意匹配模式,改变'.'的行为

Python运维开发之路《模块》的更多相关文章

  1. python运维开发之路第一天

    一.python安装及环境变量配置 1.windows7安装python 1)下载地址:https://www.python.org/downloads/windows/ 如下图: 注意:下载,用代理 ...

  2. Python运维开发基础09-函数基础【转】

    上节作业回顾 #!/usr/bin/env python3 # -*- coding:utf-8 -*- # author:Mr.chen # 实现简单的shell命令sed的替换功能 import ...

  3. Python运维开发基础08-文件基础【转】

    一,文件的其他打开模式 "+"表示可以同时读写某个文件: r+,可读写文件(可读:可写:可追加) w+,写读(不常用) a+,同a(不常用 "U"表示在读取时, ...

  4. Python运维开发基础04-语法基础【转】

    上节作业回顾(讲解+温习90分钟) #!/usr/bin/env python3 # -*- coding:utf-8 -*- # author:Mr.chen # 仅用列表+循环实现“简单的购物车程 ...

  5. Python运维开发基础01-语法基础【转】

    开篇导语 整个Python运维开发教学采用的是最新的3.5.2版,当遇到2.x和3.x版本的不同点时,会采取演示的方式,让同学们了解. 教学预计分为四大部分,Python开发基础,Python开发进阶 ...

  6. 重磅|0元学 Python运维开发,别再错过了

    51reboot 运维开发又双叒叕的搞活动了,鉴于之前 51reboot 的活动反馈,每次活动结束后(或者已经结束了很长时间)还有人在问活动的事情.这一次小编先声明一下真的不想在此次活动结束后再听到类 ...

  7. Python运维开发基础01-语法基础

    标签(空格分隔): Mr.chen之Python3.0执教笔记(QQ:215379068) --仅供北大青鸟内部学习交流使用 开发不是看出来的,开发一定是练出来的: 想学好开发,没有捷径可走,只有不断 ...

  8. Python运维开发基础10-函数基础【转】

    一,函数的非固定参数 1.1 默认参数 在定义形参的时候,提前给形参赋一个固定的值. #代码演示: def test(x,y=2): #形参里有一个默认参数 print (x) print (y) t ...

  9. Python运维开发基础07-文件基础【转】

    一,文件的基础操作 对文件操作的流程 [x] :打开文件,得到文件句柄并赋值给一个变量 [x] :通过句柄对文件进行操作 [x] :关闭文件 创建初始操作模板文件 [root@localhost sc ...

  10. Python运维开发基础06-语法基础【转】

    上节作业回顾 (讲解+温习120分钟) #!/usr/bin/env python3 # -*- coding:utf-8 -*- # author:Mr.chen # 添加商家入口和用户入口并实现物 ...

随机推荐

  1. Kubernetes(k8s)集群安装JupyterHub以及Lab

    背景 JupyterHub 为用户组带来了笔记本的强大功能.它使用户能够访问计算环境和资源,而不会给用户带来安装和维护任务的负担.用户--包括学生.研究人员和数据科学家--可以在他们自己的工作空间中完 ...

  2. LeeCode链表问题(一)

    本文中所使用的链表定义如下所示: # Definition for singly-linked list. class ListNode: def __init__(self, val=0, next ...

  3. day115:MoFang:种植园我的背包&种植园道具购买

    目录 1.我的背包 2.道具购买 1.我的背包 1.在种植园点击背包按钮打开我的背包 在种植园打开背包,orchard.html,代码: <!DOCTYPE html> <html& ...

  4. MySQL(六)存储引擎

    存储引擎 ​ 连接管理.查询缓存.解析器和执行器被归为MySQL service,而把真实存储数据的功能划分为存储引擎的功能.所以MySQL service经过查询优化后,只需按照生成的执行计划调用存 ...

  5. 深谈Spring如何解决Bean的循环依赖

    1. 什么是循环依赖 Java循环依赖指的是两个或多个类之间的相互依赖,形成了一个循环的依赖关系,这会导致程序编译失败或运行时出现异常.下面小岳就带大家来详细分析下Java循环依赖. 简单来讲就是:假 ...

  6. [OpenCV-Python] 17 形态学转换

    文章目录 OpenCV-Python:IV OpenCV中的图像处理 17 形态学转换 17.1 腐蚀 17.2 膨胀 17.3 开运算 17.4 闭运算 17.5 形态学梯度 17.6 礼帽 17. ...

  7. java镜子之反射篇

    文章目录 注解 内置注解 元注解 反射 类的初始化 类加载器 双亲委派机制 反射方法的使用 调用类的方法.成员变量.构造器等 总结 注解和反射是Java中非常重要的知识,一些优秀开源的框架都是大量运用 ...

  8. workerman、websocket简单聊天功能从0到1实现

    一.workerman安装,测试环境为linux 1.在网站根目录,用命令行安装,要是出现root权限提示,输入y回车就行,或者新建一个用户再进入安装 Linux系统可以使用以下脚本测试本机PHP环境 ...

  9. 2022-10-27:设计一个数据结构,有效地找到给定子数组的 多数元素 。 子数组的 多数元素 是在子数组中出现 threshold 次数或次数以上的元素。 实现 MajorityChecker 类

    2022-10-27:设计一个数据结构,有效地找到给定子数组的 多数元素 . 子数组的 多数元素 是在子数组中出现 threshold 次数或次数以上的元素. 实现 MajorityChecker 类 ...

  10. 2021-02-23:给定一个正数n,求n的裂开方法数。规定:后面的数不能比前面的数小 。比如4的裂开方法有: 1+1+1+1、1+1+2、1+3、2+2、4,5种,所以返回5。

    2021-02-23:给定一个正数n,求n的裂开方法数.规定:后面的数不能比前面的数小 .比如4的裂开方法有: 1+1+1+1.1+1+2.1+3.2+2.4,5种,所以返回5. 福哥答案2021-0 ...