Python学习笔记

文章目录

1. 常用操作

1.1. 数字相关操作

1.1.1. 绝对值

>>> abs(-5.0)  
5.0  

1.1.2. 数字取整

1.1.2.1. 只取整数部分int()

int(), 直接截去小数部分,剩下整数部分, 返回int型数;

>>> int(5.0) # 5  
>>> int(5.1) # 5  
>>> int(5.9) # 5  
>>> int(6.0) # 6  
>>>  
>>> int(-5.0) # -5  
>>> int(-5.1) # -5  
>>> int(-5.9) # -5  
>>> int(-6.0) # -6  
1.1.2.2. 向下取整math.floor()

math.floor() 向下取整,返回int型数;

>>> math.floor(5.0) # 5  
>>> math.floor(5.1) # 5  
>>> math.floor(5.9) # 5  
>>> math.floor(6.0) # 6  
>>>  
>>> math.floor(-5.0) # -5,小于等于-5.0 的最大整数是-5;  
>>> math.floor(-5.1) # -6,小于等于-5.1 的最大整数是-6;  
>>> math.floor(-5.9) # -6,小于等于-5.9 的最大整数是-6;  
>>> math.floor(-6.0) # -6,小于等于-6.0 的最大整数是-6;  
1.1.2.3. 向上取整 math.ceil()

math.ceil() 向上取整,返回int型数;

>>> math.ceil(5.0) # 5  
>>> math.ceil(5.1) # 6  
>>> math.ceil(5.9) # 6  
>>> math.ceil(6.0) # 6  
>>>  
>>> math.ceil(-5.0) # -5,大于等于-5.0 的最小整数是-5;  
>>> math.ceil(-5.1) # -5,大于等于-5.1 的最大整数是-5;  
>>> math.ceil(-5.9) # -5,大于等于-5.9 的最大整数是-5;  
>>> math.ceil(-6.0) # -6,大于等于-6.0 的最大整数是-6;  
1.1.2.4. 四舍五入round()

round(number[, ndigits]) 四舍五入,如果两边整数一样远,刚返回偶数一边;
参数ndigits表示小数位的数目;如果ndigits=0,返回int型数,如果ndigits>=1, 返回float型数;

>>> round(-2.5) # -2  
>>> round(-1.5) # -2  
>>> round(-0.5) # 0  
>>> round( 0.5) # 0  
>>> round( 1.5) # 2  
>>> round( 2.5) # 2  
   
>>> round(1.05, 1) # 1.1 本应该靠偶数一边是1.2, 但由于内部存储原因,返回1.1;  
#1.05  
# + 0.0000_0000_0000_0010  
# -----------------------  
# = 1.0500_0000_0000_0012  
# 所以1.05更靠近1.1 这边;  
   
   
>>> round(1.15, 1) # 1.1 本应该靠偶数一边是1.2, 但由于内部存储原因,返回1.1;  
#1.15  
# + 0.0000_0000_0000_0002  
# -----------------------  
# = 1.1500_0000_0000_0001  
# 所以1.05更靠近1.1 这边;  
   
   
>>> round(1.25, 1) # 1.2  
>>> round(1.35, 1) # 1.4  
>>> round(1.45, 1) # 1.4  
>>> round(1.55, 1) # 1.6  
>>> round(1.65, 1) # 1.6  
   
>>> round(2.675, 2) # 2.67, 本应该靠偶数一边是2.68, 但由于内部存储原因,返回2.67;  

在python2.7的doc中,round()的最后写着,"Values are rounded to the closest multiple of 10 to the power minus ndigits; if two multiples are equally close, rounding is done away from 0."保留值将保留到离上一位更近的一端(四舍六入),如果距离两端一样远,则保留到离0远的一边。所以round(0.5)会近似到1,而round(-0.5)会近似到-1。

但是到了python3.5的doc中,文档变成了"values are rounded to the closest multiple of 10 to the power minus ndigits; if two multiples are equally close, rounding is done toward the even choice."如果距离两边一样远,会保留到偶数的一边。比如round(0.5)和round(-0.5)都会保留到0,而round(1.5)会保留到2。

round(2.675, 2) 的结果,不论我们从python2还是3来看,结果都应该是2.68的,结果它偏偏是2.67,为什么?这跟浮点数的精度有关。我们知道在机器中浮点数不一定能精确表达,因为换算成一串1和0后可能是无限位数的,机器已经做出了截断处理。那么在机器中保存的2.675这个数字就比实际数字要小那么一点点。这一点点就导致了它离2.67要更近一点点,所以保留两位小数时就近似到了2.67。

1.1.3. 乘方、开方

pow(x, y) # 求x的y次方;

>>> pow(3, 2) # 9,求平方,返回int型数;  
>>> pow(3, 1/2) # 1.7320508075688772, 1/2次方即开方运算;  
>>> pow(4, 1/2) # 2.0, 平方根返回的是float型数;  

math.pow(),与pow()类似

>>> math.pow(3, 2) # 9.0, 返回的是float型数  

对于求平方根,除了可以使用math.pow(x, 1/2)外,还有专门的平方根函数math.sqrt(x)

>>> math.sqrt(2) # 1.4142135623730951,求平方根  
>>> math.sqrt(4) # 2.0, 平方根返回的是float型数;  

1.1.4. 三角函数、对数

三角函数

>>> math.pi # 3.1415_9265_3589_793, 使用math.pi可以调用π;  
>>> math.sin(math.pi / 6) # 0.4999_9999_9999_9999_4,得到的并不是0.5;  
>>> math.cos(math.pi / 3) # 0.5000_0000_0000_0001,得到的并不是0.5;  
>>> math.tan(math.pi / 4) # 0.9999_9999_9999_9999,得到的并不是1.0;  

对数,math.log(A, B=e) 以B为底,A的对数,默认以e为底;

>>> math.e             # 2.7182_8182_8459_045,自然常数e;
>>> math.log(100, 10) # 2.0,返回的是float型数;
>>> math.log(math.e)  # 1.0,

1.1.5. 随机数

1.1.5.1. 随机整数

randint(a, b),[a, b]之间的整数,包含b;

>>> import random  
>>> random.randint(10, 20) # 16,返回[10, 20]之间的随机整数;算个bug吧  
>>> random.randint(20, 10) # 报错ValueError,参数对顺序有要求;  
>>> random.randint(10, 10) # 10,上下限相同,返回这个数;  

randrange(start, stop=None, step=1, _int=<class ‘int’>), 不包含stop

>>> random.randrange(10, 20, 2) # 返回[10, 20)之间的偶数,不包括stop  
1.1.5.2. 随机浮点数

uniform(a, b), [a, b]之间的浮点数,包含b;

>>> import random  
>>> random.uniform(10, 20) # 12.132xxxxx,返回[10, 20]之间的随机浮点数;  
>>> random.uniform(20, 10) # 10.414xxxxx,uniform(),两个参数不关心顺序;  
>>> random.uniform(10, 10) # 10.0,上下限相同,返回这个数;  

random.random(), [0, 1)之间的浮点数,不包含1;不需要参数

>>> random.random()  
0.1862385***  
1.1.5.3. 在待选中随机选择

语法:random.choice(seq)
参数:seq可以是列表、元组、字符串
返回:返回一个元素

>>> import random  
>>> random.choice([1, 3, 5]) # 从list中随机选择一个  
3  
>>> random.choice('abc!@#') # 从str中随机选择一个  
#  

语法:random.sample(seq, n)
参数:seq,列表、元组、字符串;n,数目;
返回:返回一个列表

>>> import random  
>>> random.sample([1, 3, 5, 7, 9], 3) # 从list中随机选择三个  
[5, 1, 3]  
>>> random.sample('abc!@#') # 从str中随机选择三个  
['a', '#', 'b']  
1.1.5.4. 打乱序列

语法:random.shuffle(x, random=None)
参数:x,一个list;random,??
返回:返回None,传入的lst会被改变

>>> import random  
>>> L0 = [1, 2, 3, 4, 5]  
>>> random.shuffle(L0) # 将L0洗牌, 该语句返回None  
>>> L0  
[4, 5, 3, 1, 2]  

1.1.6. 平均值/方差/标准差

需要第三方模块 numpy

import numpy as np

f_mean = np.mean(_list) # 平均值
f_var = np.var(_list) # 方差
f_std = np.std(_list, ddof=1) # 标准差

1.2. 调用Tcl

>>> import tkinter  
>>> interp tkinter.Tcl()  

1.2.1. 通过eval调用tcl命令,返回值为str

>>> # 调用tcl语句  
>>> interp.eval('source xx.tcl')  
>>>  
>>> # 调用array names返回str,split后赋值给list  
>>> list_a0_names = interp.eval('array names a0').split()  
>>>  
>>> # 调用llength 返回str,int后赋值给整形变量  
>>> i_length = int(interp.eval('llength $list0'))  
>>>  
>>> # 调用lindex返回str  
>>> s_key = interp.eval('lindex $list0 0')  

1.2.2. 通过setvar给变量赋值

>>> interp.setvar('s_tmp', 'this is a tmp string')  

1.2.3. 通过getvar得到变量的值

>>> interp.getvar('s_tmp') # 'this is a tmp string'  
>>>  
>>> s_tmp_var = 's_tmp'  
>>> interp.getvar(s_tmp_var) # 'this is a tmp string',使用变量名代替's_tmp'  

1.3. 时间

感觉datetime模块专业些

1.3.1. time模块

时间元组: (年,月,日,时,分,秒,周几,年中第几天,是否夏令时),手工指定时,最后3项可以指定为0;
时间戳:指定时间距1970-01-01 00:00:00总秒数,float型数;

>>> import time  
1.3.1.1. 求当前时间戳
>>> time.time() # 1531722744.1899934,float型数  
1.3.1.2. 求给定时间的时间戳(输入时间元组)
>>> t = (2018,7,16,14,38,59,0,0,0) # 时间元组,最后3项可以指定为0  
>>> time.mktime(t) # 1531723139.0,给定时间的时间戳,注意参数只有一个而不是9个  
1.3.1.3. 按指定格式显示当前时间,返回字符串
>>> time.strftime('%Y-%m-%d %H:%M:%S') # '2018-07-16 14:54:26',返回str  
1.3.1.4. 指定时间字符串,按指定格式拆分为数组
>>> str = '2018-07-1615:20:00'  
>>> time.strptime(str, '%Y-%m-%d %H:%M:%S') # 返回time.struct_time  

返回time.struct_time(tm_year=2018, tm_mon=7, tm_mday=16, tm_hour=15, tm_min=20, tm_sec=0, tm_wday=0, tm_yday=197, tm_isdst=-1)
如果时间格式串与字符串不匹配会报告错误:time data xxx does not match format ‘%xxx’

1.3.1.5. 显示英文时间
>>> t = (2018,7,16,14,38,59,0,0,0)  
>>> time.asctime(t) # 'Mon Jul 16 14:38:59 2018',返回str  
1.3.1.6. 进程挂起1s时间
>>> time.sleep(1)
1.3.1.7. 格式化字符串
格式 说明
%y 两位数年份(00-99)
%Y 四位数年份(0000-9999)
%m 月份(01-12)
%d 月内的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身

1.3.2. datetime模块

时间元组: (年,月,日,时,分,秒,微秒),注意这个时间元组有7个元素;
时间戳:给定的时间距离开始时间(1970-01-01 00:00:00)总秒数,float型数;
datetime模块中有一个datetime类,所有的信息都存储在这个类中

1.3.2.1. 初始化datatime类
>>> import datetime
>>> dt = datetime.datetime # 给datetime类一个别名
>>> type(dt)
# <class 'type'>
1.3.2.2. 得到一个指定具体时间的datetime类dt0
>>> dt0 = dt(2018,7,16,17,7,30,1)
>>> type(dt0)# 可以从dt0中取想要的数据
# <class 'datetime.datetime'>
1.3.2.3. 分别取年、月、日、时、分、秒、微秒
>>> dt0.year# 取年份, 返回值为int
2018
>>> dt0.month # 取月份, 返回值为int
7
>>> dt0.day# 取日期,返回值为int
16
>>> dt0.hour# 取时,返回值为int
14
>>> dt0.minute# 取分,返回值为int
29
>>> dt0.second# 取秒,返回值为int
20
>>> dt0.microsecond# 取微秒,返回值为int
253127
1.3.2.4. 取date和time
>>> dt0.date()# 取年月日, 返回datetime.date类
datetime.date(2018,7,16)
>>> dt0.time()# 取时间, 返回datetime.time类
datetime.time(17,7,30,1)
1.3.2.5. 取周几、日历
>>> # 取周几:
>>> dt0.weekday()#周一为0, 返回值为int
0
>>> dt0.isoweekday() #周一为1, 返回值为int
1
>>> dt0.isocalendar() # 取日历, 返回tuple,
(2018, 29,1)# 含义:(年,第几周,周几);
1.3.2.6. 公元天数换算
>>> dt0.toordinal() # 到公元元年的天数, 返回值为int
736891
>>> dt1 = dt0.fromordinal(54) # 指定到公元元年的天数,算datetime,返回datetime类
>>> dt1
datetime.datetime(1,2,23,0,0)
1.3.2.7. 取当前时间、零时区时间
>>> # 取当前时间:返回datetime类
>>> dt2 = dt.today()
>>> dt2
datetime.datetime(2018,7,17,10,31,53,757945)
>>> dt3 = dt.now()
>>> dt3
datetime.datetime(2018,7,17,10,31,53,758002)
>>>
>>> # 取零时区时间:返回datetime类
>>> dt4 = dt.utcnow()
>>> dt4 # 中国是东8区,所以零时区时间=中国时间-8 (东边日出早,小时数值大)
datetime.datetime(2018,7, 17, 2, 31, 53, 758017)
1.3.2.8. 取时间的标准str
>>> dt0.isoformat() # 得到时间的标准str,返回值为str
'2018-07-16T17:07:30.1'
1.3.2.9. 时间戳
>>> dt0.timestamp() # 从datetime取时间戳: 返回float,小数位表示毫秒数
1531732050.000001
>>> dt5 = dt0.fromtimestamp(1531732650.000001) # 从时间戳取datetime: 返回datetime类
>>> dt5
datetime.datetime(2018,7,16,17,17,30,1)
1.3.2.10. 自定义格式时间、英文格式时间
>>> dt.strftime('%Y-%m-%d') # 按自定义格式返回时间str
'2018-07-16'
>>> dt.ctime() # 取英文格式的时间,返回str
'Mon Jul 16 17:07:30 2018'
1.3.2.11. 时间元组
>>> dt0.timetuple() # 得到9个元素的时间元组,
time.struct_time(tm_year=2018, tm_mon=7,tm_mday=16, tm_hour=17, tm_min=07, tm_sec=30,tm_wday=1, tm_yday=190,tm_isdst=-1)
1.3.2.12. 给定时间str,按时间格式拆开,返回datetime.datetime类
>>> str='2049-12-31 23:59:59'
>>> dt6 = dt.strptime(str, '%Y-%m-%d %X')
>>> dt6
datetime.datetime(2049,12,31,23,59,59)
1.3.2.13. datetime加减
>>> now = datetime.datetime.now()
datetime.datetime(2017,8,23,14,21,33,796979)
>>>
>>> now + datetime.timedelta(hours=10)
datetime.datetime(2017,8,24,0,21,33,796979)
>>>
>>> now - datetime.timedelta(days=1)
datetime.datetime(2017,8,22,14,21,33,796979)
>>>
>>> now + datetime.timedelta(days=2, hours=12)
datetime.datetime(2017,8,26,2,21,33,796979)

1.4. 进制转换

1.4.1. 使用bin/oct/hex、int

1.4.1.1. 十进制-> 其它进制
>>> #使用bin/oct/hex,输入int,返回str;
>>> bin(50) # '0b110010',十进制 -> 二进制,返回的值为字符串,以0b开头;
>>> oct(50) # '0o62',十进制 -> 八进制,返回的值为字符串,以0o开头;
>>> hex(50) # '0x32', 十进制 -> 十六进制,返回的值为字符串,以0x开头;
1.4.1.2. 其它进制-> 十进制
>>> s_bin = '110010'# 二进制str;
>>> i_int= int(str(s_bin), 2) # 50, 输入二进制str,返回十进制整数;
>>>
>>> i_int = int(str(62), base=8)# 50,输入八进制str,返回十进制整数;
>>> i_int = int(str(32), base=16) # 50,输入十六进制str,返回十进制整数;

1.4.2. 使用format

缺点是format的参数只能是各进制的整数,不能是str;
所有需要把参数使用int()处理后再使用format, 如:
‘{n:08b}’.format(n=int(s0, base=16))

1.4.2.1. 转为二进制
>>> '{:b}'.format(13)      #输入十进制整数,输出二进制str,:b表示转为二进制;
'1101'  
>>> '{:08b}'.format(13)    #输入十进制整数,输出二进制str,:08b表示转为二进制,宽度为8,不足补0;  
'00001101'  
>>> '{:08b}'.format(0x000D)#输入十六进制整数,输出二进制str;  
'00001101'  
>>> s0='0xd'  
>>> '{n:08b}'.format(n=int(s0, base=16)) #输入十六进制str, 转为二进制, 中间需要经过int()处理  
'00001101'  
1.4.2.2. 转为八进制
>>> '{:o}'.format(13)   #输入十进制整数,输出八进制str,:o表示转为八进制;  
'15'  
>>> '{:08o}'.format(13) #输入十进制整数,输出八进制str,:08o表示转为八进制,宽度为8,不足补0;  
'00000015'  
>>> '{:08b}'.format(0xD)#输入十六进制整数,输出八进制str;  
'00000015'  
1.4.2.3. 转为十六进制

使用大写的:X, 可以转出的16进制字符.

>>> '{:x}'.format(13)   #输入十进制整数,输出十六进制str,:x表示转为十六进制
'd'  
>>> '{:04x}'.format(13) #输入十进制整数,输出十六进制str,:04x表示转为十六进制,宽度为4,不足补0
'000d'  
>>> '{:04x}'.format(0b01101)#输入二进制整数,输出十六进制str;  
'000d'  
>>> '{:04x}'.format(int('0b01101', base=2)#输入二进制str,输出十六进制str;
'000d'  

1.5. 格式化字符

1.5.1. 使用%

%的常用转换类型

转换 说明 示例
d,i 整型 ‘%i’%(4.3) 返回’4’
u 无符号整型
f 浮点型, m.dddd ‘%5.3f’%(1/3) 返回’0.333’
e 浮点型, m.dddde+/-xx ‘%5.3e’%(1/3) 返回’3.333e-01’
E 浮点型, m.ddddE+/-xx ‘%5.3E’%(1/3) 返回’3.333E-01’
g
c char, 单字符 ‘%c’%(78), 返回’N’
s str或能用str()转换的数据 ‘%s’%(1/3), 返回’0.3333333333333333’
% 输入一个% ‘30%%’%(), 返回’30%’
1.5.1.1. 对整数指定宽度
>>> n = 5
>>> s = '%8d'%(n)# '5',默认为右对齐;
>>> s = '%08d'%(n)# '00000005',前面补0;
>>> s = '%-8d'%(n)# '5', 使用负号,左对齐;
1.5.1.2. 通过变量指定宽度
>>> w = 8
>>> n = 5
>>> s = '%*d'%(w, n)# '5',默认右对齐;
>>> s = '%0*d'%(w, n) # '00000005',前面补0;
>>> s = '%-*d'%(w, n) # '5',左对齐;
1.5.1.3. 对小数指定宽度

只指定总宽度

>>> n = 3.1415926 # 整数部分1位,小数部分7位
>>> '%5f'%(n) # '3.141593' n长度超过5,所以不舍去bit,但为什么最后的6被四舍五入了?
>>> '%6f'%(n) # '3.141593' n长度超过6,所以不舍去bit,但为什么最后的6被四舍五入了?
>>> '%7f'%(n) # '3.141593' n长度超过7,所以不舍去bit,但为什么最后的6被四舍五入了?
>>> '%8f'%(n) # ' 3.141593' 整数部分2bit,小数部分6bit,共8bit;

指定总宽度和小数宽度

>>> n = 3.1415926 # 整数部分1位,小数部分7位
>>> '%5.0f'%(n) # '3',共5bit, 小数部分0bit,整数部分5bit,小数点0bit;
>>> '%5.1f'%(n) # '3.1',共5bit, 小数部分1bit,整数部分3bit,小数点1bit;
>>> '%5.3f'%(n) # '3.142',共5bit, 小数部分3bit,整数部分1bit,小数点1bit;
>>> '%5.4f'%(n) # '3.1416' 小数部分4bit,整数部分1bit,小数点1bit,超过了5bit,实际共6bit,相当于'%6.4f'%(n);
>>> '%5.5f'%(n) # '3.14159' 小数部分5bit,整数部分1bit,小数点1bit,超过了5bit,实际共7bit,相当于'%7.5f'%(n);
>>> '%05.1f'%(n) # '003.1' 小数部分1bit,整数部分3bit,小数点1bit,共5bit;
1.5.1.4. 通过变量指定总宽度和小数宽度
>>> w_all = 5
>>> w_frac = 1
>>> '%0*.*f'%(w_all, w_frac, n) # '003.1' 小数部分1bit,整数部分3bit,小数点1bit,共5bit;

1.5.2. 使用format

format是python2.6后增加的功能

1.5.2.1. 通过位置映射
>>> '{} and {}'.format('hello', 'world') # 'hello and world' ,不指定位置,按默认顺序;
>>> '{0} and {1} or {0}'.format('hello', 'world') # 'hello and world or hello' ,指定位置,位置可以重复使用;
1.5.2.2. 通过key映射
>>> '{name} is {age} years old'.format(age=18, name='Jim') # 'Jim is 18 years old'
1.5.2.3. 通过下标映射
>>> list_info = ['Jim', 18]
>>> '{0[0]} is {0[1]} years old'.format(list_info) # 'Jim is 18 years old'
>>> '{list_arg[0]} is {list_arg[1]} years old'.format(list_arg=list_info) # 'Jim is 18 years old'
1.5.2.4. 填充与对齐

语法: {:[填充符][对齐方式][宽度]}
对齐方式:’^‘表示居中,’<‘表示左对齐,’>'表示右对齐;
宽度: 通过数字或变量指定;

>>> '{s0:<10}'.format(s0='abcd') #左对齐  
'abcd      '  
>>> '{s0:^10}'.format(s0='abcd') #居中对齐  
'   abcd   '  
>>> '{s0:>10}'.format(s0='abcd') #右对齐  
'      abcd'  
>>> '{s0:0>10}'.format(s0='abcd') #不足补0    
'000000abcd'  
>>> '{s0:x^10}'.format(s0='abcd') #不足补x  
'xxxabcdxxx'  
>>> '{s0:x^{w}}'.format(s0='abcd', w=10) #通过变量指定宽度  
'xxxabcdxxx'  
>>> '{s0:{t}^{w}}'.format(s0='abcd',t='x', w=10) #通过变量指定填充字符, 好像只支持一个字符  
'xxxabcdxxx'  
>>> '{s0:{t}{d}{w}}'.format(s0='abcd',t='x', d='^', w=10) #通过变量指定对齐方式  
'xxxabcdxxx'  
out
1.5.2.5. 指定小数部分宽度
>>> '{:.3f}'.format(0.123456)# '0.123',.3f表示小数部分占3bit;
>>> '{:7.3f}'.format(0.123456) # '[ ][ ]0.123',7.3f表示小数部分占3bit,字符总宽度7bit;
>>> '{n:{w_all}.{w_frac}f}'.format(m=0.123456, w_all=7, w_frac=3) # '[ ][ ]0.123',通过变量指定宽度;
1.5.2.6. 添加千分位分隔符
>>> '{:,}'.format(1234567.89123) # 1,234,567.89123 , ':,'表示添加千分位分隔符;

1.6. 排序

1.6.1. list内置方法sort()

语法:sort(key=None, reverse=False)

参数:
key,一个函数,作用是指定比较的元素, 通常由lambda指定, 可以指定多个值lambda x: (x[0], x[1], x[2]);
reverse,bool类型,False升序,True降序, 默认升序;

说明:
sort方法会改变list本身, 并返回None, 所以不能这么写a = b.sort();
python3中,sort删除了cmp参数

例子:

>>> L0 = [('a', 1), ('b', 3), ('d', 2), ('c', 1)]  
>>>   
>>> # 默认排序  
>>> L0.sort()  
>>> L0  
[('a', 1), ('b', 3), ('c', 1), ('d', 2)]  
>>>   
>>> # key=lambda x:x[1], 按L0元素(是一个tuple)的第1个元素排序,  
>>> # 也可以指定key=lambda x:(x[1], x[0])进行多维排序  
>>> L0.sort(key=lambda x:x[1])  
>>> L0  
[('a', 1), ('c', 1), ('d', 2), ('b', 3)]  
>>>   
>>> # 降序排序  
>>> L0.sort(reverse=True) # 默认按升序排序,通过reverse=True按降序排列;  
>>> L0  
[('d', 2), ('c', 1), ('b', 3), ('a', 1)]  
>>>   
>>> # sort返回值是None, 即list.sort()没返回任何对象  
>>> print(L0.sort())  
None  

1.6.2. 全局方法sorted()

语法:sorted(iterable, key=None, reverse=False)
参数:
iterable: 可迭代对象
key:sorted是一个高阶函数,可以接收一个key函数来自定义排序,key指定的函数作用于list的每一个元素上,并根据key函数的返回值进行排序, 参见list的内置函数sort的key参数.
reverser:bool类型,False升序,True降序; 默认升序.

注意:sorted方法不改变原序列,而是返回一个新的序列;

例1:按绝对值排序、按忽略大小写排序、降序排序

>>> sorted([36,15,-12,9,-21], key=abs) #按绝对值大小排序;  
[9, -12, 15, -21, 36]  
>>> sorted(['bob', 'About', 'Zoo', 'Credit'], key=str.lower) # 按忽略大小写排序;  
['About', 'bob', 'Credit', 'Zoo']  
>>> sorted(['bob','About','Zoo','Credit'], key = str.lower, reverse=True) # 按忽略大小写反向排序;  
['Zoo', 'Credit', 'bob', 'About']   

例2:按字典的key/value排序

>>> d={
   }  
>>> d['a'] = 3  
>>> d['b'] = 4  
>>> d['c'] = 2  
>>> d['d'] = 1  
>>> sorted(d.items(), key=lambda x:x[0]) #按key排序,返回[('a',3),('b',4),('c',2),('d',1)]  
>>> sorted(d.items(), key=lambda x:x[1]) #按value排序,返回[('d',1),('c',2),('a',3),('b',4)]  

例3:按多条件排序

>>> d0 = {
   }  
>>> d0['id0'] = {
   'score':90, 'name':'name1', 'age':14}  
>>> d0['id1'] = {
   'score':90, 'name':'name3', 'age':12}  
>>> d0['id2'] = {
   'score':60, 'name':'name2', 'age':13}  
>>> d0['id3'] = {
   'score':90, 'name':'name3', 'age':11}  
>>>  
>>> list_id_sorted = sorted(  
...     d0.keys(),  # 对d0.keys()排序, 所以返回的是id组成的list.
...     key=lambda s_id:(  
...         -d0[s_id]['score'], # 按分数逆序排列,-表示逆序  
...         d0[s_id]['name']  , # 按姓名顺序排列  
...         s_id              , # 按学号顺序排列  
...     )  
... )  
...  
>>> for s_id in list_id_sorted:  
...     print(f'{d0[s_id]['score']} {d0[s_id]['name']} {s_id}')  
...  
90 name1 id0 # 90分排在前;  
90 name3 id1 # 同样90分,按姓名排序;  
90 name3 id3 # 同样90分,同样name3,按学号排序;  
60 name2 id2 # 60分排在后;  

1.6.3. key参数

key参数
可以是一个简单的函数, 比如key=str或key=str.lower,
可以是一个通过lambda指定的函数 key=lambda x:(x[0], x[1])
可以是一个自定义的函数:

def sort_str(x):  
  m = re.match(r'^(\S+?)(\d+)$', x)  
  if m:  
     _name = m.group(1)  
     _idx = int(m.group(2))  
  else:  
    _name = x  
    _idx = 0  
  return _name, idx # 先按前导字符排序, 后按后缀数字排序  
                    # 这样'a2'排在'a10'前面, 'a*'排在'b0'前面.  
  
L0 = ['a2', 'b3', 'a1', 'b20', 'a0', 'a10', 'a9', 'b0']  
L1 = sorted(L0, key=sort_str)   
print(L1) # ['a0', 'a1', 'a2', 'a9', 'a10', 'b0', 'b3', 'b20']  

1.7. 处理命令行参数

1.7.1. 使用步骤

使用步骤如下:

# 导入模块  
import argparse  
  
# 获取parser, description文本会显示在help信息中  
parser = argparse.ArgumentParser(description='args discrip')  
  
# 添加选项, 具体选项类型见后面各节  
parser.add_argument('-a')  
  
# 解析选项  
args = parser.parse_args(sys.argv[1:])  
  
# 使用选项  
print(args.a)  

对sys.argv[1:]的说明:

sys.argv         # 一个列表,存储命令行参数.  
sys.argv[0]      # 脚本名.  
sys.argv[1:]     # 命令行参数.  
sys.argv[1][2:]  # 截取第一个参数第2bit之后的内容;  

1.7.2. 位置参数

# 位置参数可以实现类似于vcs a.v b.v的选项处理,   
# 如下例, vfiles是位置参数,不需要使用'-vfile 或者-xx'这种形式指定选项内容;  
#         default=[] 表示默认参数为空list;  
#         nargs='*'  表示可以是0个或多个参数;  
>>> parser.add_argument('vfiles', type=str,default=[], nargs='*')  
_StoreAction(optine_strings=[], dest='vfiles', nargs='*', const=None, default=[], Type=<class 'str'>, choices=None, help=None, metavar=None)  

1.7.3. flag类型的选项(选项本身无参数)

flag类型选项本身无参数, 根据"命令行是否有该选项" 和 “该选项声明值/默认值” 来决定选项实际值(注意, 并不是声明选项, 则该选项为True, 不声明为False, 而是内部可配置):

>>> parser.add_argument(  
...     '-a',                # 选项名称  
...     action='store_true', # 如果声明-a, 则a=True;  
...     default=False        # 如果不声明(默认)-a, 则a=False;  
... )  
_StoreTrueAction(optine_strings=['-a'], dest='a', nargs=0, const=True, default=False, Type=None, choices=None, help=None, metavar=None)  
  
>>>   
>>> parser.add_argument(  
...     '-b',   
...     '--b_long_opt',       # b有额外的长选项名称: --b_long_opt  
...     action='store_false', # 如果声明-b, 则b=False  
...     default=True,         # 如果不声明(默认)-b, 则b=True  
...     dest='b_new_name'     # 内部使用b_new_name取用该选项(而不能使用b)  
)  
_StoreTrueAction(optine_strings=['-b', '--b_long_opt'], dest='b_new_name', nargs=0, const=False, default=True, Type=None, choices=None, help=None, metavar=None)  

注意,不会有以下两种情况,因为这两种情况下,无论选项是否定义,内部得到的值都一样,没有意义;

>>> # action='store_true', default=True,声明选项和默认值都是True  
>>> # action='store_false', default=False,声明选项和默认值都是False  

通过parse一个内部数组来进行验证,实际使用中是parse真正的命令行数组sys.argv[1:], 注意sys.argv[0]表示的是脚本名称;

测试1:#-a -b都没声明,所以都是default值

>>> lst_args=[]  
>>> args = parser.parse_args(lst_args)  
>>> args.a          # 未声名-a,所以args.a的值为default值False;  
False  
>>> args.b_new_name # 未声名-b,所以args.b_new_name值为默认值True;  
True  
>>> args.b  # 由于使用了dest, 所以args.b会报错, 只能使用args.b_new_name获取 
AttributeError: 'Namespace' object has no sttribute 'b'  

测试2:-a -b都声明,所以都是action store值

>>> lst_args=['-ab'] # -a和-b是短选项, 可以合并使用'-ab'表示'-a' '-b'  
>>> args = parser.parse_args(lst_args)  
>>> args.a          # 声名了-a,所以args.a的值为声明值True;  
True  
>>> args.b_new_name # 声名了-b,所以args.b_new_name值为声明值False;  
False  

测试3:使用长选项,-a -b都声明,所以都是store值

>>> lst_args=['-a', '--b_long_opt'] # --b_long_opt是长选项, 需要使用双短线('--')进行声明  
>>> args = parser.parse_args(lst_args)  
>>> args.a          # 声名了-a,所以args.a的值为声明值True;  
True  
>>> args.b_new_name # 声名了-b,所以args.b_new_name值为声明值False;  
False  

1.7.4. 必选选项(选项必须声明, 不声明会报错)

>>> parser.add_argument(  
...     '-c',          # 选项名称  
...     type=int,      # 选项类型是整数  
...     required=True  # 选项是必选选项  
)  
_StoreAction(optine_strings=['-c'], dest='c', nargs=None, const=None, default=None, Type=<class 'int'>, choices=None, help=None, metavar=None)  
>>>  
>>> # 选项-c必须声明,否则报错:error:the following argument are required:-c  
>>> lst_args=['-c', '3']  
>>> args = parser.parse_args(lst_args)  
>>>  
>>> # 选项-c类型为int,所以str '3'传到args.c时,会转类型为int 3;  
>>> print(args.c)  
3  

1.7.5. 可选选项,可带默认值

-d 为str类型的可选选项,默认值为’default_d’

-d 为str类型的可选选项,默认值为'default_d'  
>>> parser.add_argument(  
...     '-d',                  # 选项名  
...     type     = str,        # 选项类型  
...     required = False,      # '-d'是可选选项  
...     default  = 'default_d' # '-d'不声明时, 默认值为'default_d'  
)  
_StoreTrueAction(optine_strings=['-d'], dest='d'
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值