0.概述
本文记录一下python中的用法,作为简单的记录,必要时再予以补充。
1.argparse用法
argparse
是Python内置的命令行参数解析模块。在使用add_argument
方法时,可以通过action
参数指定对参数的特殊处理方式。下面将详细介绍parser.add_argument
中的action
使用的完整攻略,包括常用的几种action
和它们的用法。
1)action='store'
使用store
时,将参数值存储到args
的命名空间中。如果在命令行中指定了参数,则存储指定的参数值;否则,将使用默认值。例如:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', action='store', default='bar')
args = parser.parse_args()
print(args.foo)
上面的代码在命令行中运行时不指定--foo
参数值,则args.foo
的值为'bar'
。
2) action='store_const'
使用store_const
时,将常量(const
)值存储到args
的命名空间中,该常量值与指定的参数名相对应。如果在命令行中指定了该参数,则将该常量值存储到args
的命名空间中。例如:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', action='store_const', const=42)
args = parser.parse_args()
print(args.foo)
上面的代码在命令行中运行时指定--foo
参数,则args.foo
的值为42
;否则为None
。
3) 其他常用action
选项
除了上述两种action
选项,还有一些常用的选项:
store_true
: 将布尔值True
存储到args的命名空间中。store_false
: 将布尔值False
存储到args的命名空间中。append
: 将值追加到列表中。append_const
: 将常量值追加到列表中。version
: 打印程序版本号并退出。
下面是store_true
和store_false
的示例:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', action='store_true')
parser.add_argument('--bar', action='store_false')
args = parser.parse_args()
print(args.foo)
print(args.bar)
上面的代码在命令行中运行时指定--foo
参数,则args.foo
的值为True
;若指定--bar
参数,则args.bar
的值为False
。
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--debug', dest='debug_mode', action='store_true')
parser.add_argument('--no-debug', dest='debug_mode', action='store_false')
parser.set_defaults(debug_mode=False)
args = parser.parse_args()
print(args.debug_mode)
上面的代码在命令行中运行时指定--debug
参数,则args.debug_mode
的值为True
; 若指定--no-debug
参数,则args.debug_mode
的值为False
。若不指定任何参数则默认为False
。
这就是parser.add_argument
中的action
使用的完整攻略。
2.datetime
datetime是模块,datetime模块还包含一个datetime类,通过from datetime import datetime导入的才是datetime这个类。
strptime():str-parse-time # string to datetime
strftime():str-format-time # datetime to string
1) strptime
用户输入的日期和时间是字符串,要处理日期和时间,首先必须把str转换为datetime。转换方法是通过datetime.strptime()实现,需要一个日期和时间的格式化字符串:
>>> from datetime import datetime
>>> cday = datetime.strptime('2022-3-1 18:20:20', '%Y-%m-%d %H:%M:%S')
>>> print(cday)
2022-03-01 18:20:20
2) strftime
后台提取到datetime对象后,要把它格式化为字符串显示给用户,就需要转换为str,转换方法是通过strftime()实现的,同样需要一个日期和时间的格式化字符串:
>>> from datetime import datetime
>>> now = datetime.now()
>>> print(now.strftime('%a, %b %d %H:%M'))
Sun, May 01 00:16
3) datetime加减:
对日期和时间进行加减实际上就是把datetime往后或往前计算,得到新的datetime。加减可以直接用+和-运算符,不过需要导入timedelta这个类:
>>> from datetime import datetime, timedelta
>>> now = datetime.now()
>>> now
datetime.datetime(2022, 5, 1, 0, 16, 59, 248600)
>>> now + timedelta(hours=10)
datetime.datetime(2022, 5, 1, 10, 16, 59, 248600)
>>> now - timedelta(days=1)
datetime.datetime(2022, 4, 30, 0, 16, 59, 248600)
>>> now + timedelta(days=2, hours=12)
datetime.datetime(2022, 5, 3, 12, 16, 59, 248600)
3.sort
partial_indices.sort(key = lambda x: lengths[x], reverse = True)
#e.g:
partial_indices = [2,3,5,1,0,4]
lengths=[9,6,7,2,3,5,18,11]
#firstly, get value=[7, 2, 5, 6, 9, 3]
value=[lengths[x] for x in partial_indices]
#then, get value= [9, 7, 6, 5, 3, 2]
value.sort(reverse = True)
#lastly, get the index of the sorted [9, 7, 6, 5, 3, 2] in original [9,6,7,2,3,5,18,11]
# result is:
[0, 2, 1, 5, 4, 3]
4.multiprocessing
import threading
class MyThread(threading.Thread):
def __init__(self, func, args=[()], name=''):
threading.Thread.__init__(self)
self.name = name
self.func = func
self.args = args
self.result = []
def run(self):
for arg in self.args:
if arg is None:
self.result.append(self.func())
else:
self.result.append(self.func(*arg))
def get_result(self):
return self.result
def StartThreadTask(func, args=[()], thrd_cnt=1, is_syn=True):
thrd_lst = []
cnt = int(len(args)/thrd_cnt) # e.g int(18/16)=1
thrd_cnt1 = len(args)%thrd_cnt # e.g 2
cnt1 = cnt+1 # e.g 2
for i in range(thrd_cnt1): # 0~1
thrd_args = args[i*cnt1:i*cnt1+cnt1]
thrd = MyThread(func, thrd_args, str(i))
thrd_lst.append(thrd) # A thread list,length:5
for i in range(thrd_cnt1,thrd_cnt): # range:5~15
thrd_args = args[thrd_cnt1+i*cnt:thrd_cnt1+i*cnt+cnt] # e.g args[5+0:5+0+0]
thrd = MyThread(func, thrd_args, str(i))
thrd_lst.append(thrd)
for thrd in thrd_lst:
thrd.start()
if is_syn:
result = []
for thrd in thrd_lst:
thrd.join()
result += thrd.get_result()
return result
5.format用法
对于Python3 开始,以下列出三种常用的字符串格式化的功能。
1)C语音相似的占位符格式化输出(古老版本)
name='scott'
age=11
print("My name is %s,My age is %d" %(name,age))
2) format一般化格式化输出(常用版本)
name='scott'
age=11
print("My name is %s,My age is %d" %(name,age))
下表展示了 str.format() 格式化数字的具体方法,涵盖多种形式:
>>> print("{:.2f}".format(3.1415926));
3.14
数字 | 格式 | 输出 | 描述 |
---|---|---|---|
3.1415926 | {:.2f} | 3.14 | 保留小数点后两位 |
3.1415926 | {:+.2f} | +3.14 | 带符号保留小数点后两位 |
-1 | {:+.2f} | -1.00 | 带符号保留小数点后两位 |
2.71828 | {:.0f} | 3 | 不带小数 |
5 | {:0>2d} | 05 | 数字补零 (填充左边, 宽度为2) |
5 | {:x<4d} | 5xxx | 数字补x (填充右边, 宽度为4) |
10 | {:x<4d} | 10xx | 数字补x (填充右边, 宽度为4) |
1000000 | {:,} | 1,000,000 | 以逗号分隔的数字格式 |
0.25 | {:.2%} | 25.00% | 百分比格式 |
1000000000 | {:.2e} | 1.00e+09 | 指数记法 |
13 | {:10d} | 13 | 右对齐 (默认, 宽度为10) |
13 | {:<10d} | 13 | 左对齐 (宽度为10) |
13 | {:^10d} | 13 | 中间对齐 (宽度为10) |
11 | '{:b}'.format(11) '{:d}'.format(11) '{:o}'.format(11) '{:x}'.format(11) '{:#x}'.format(11) '{:#X}'.format(11) | 1011 11 13 b 0xb 0XB | 进制 |
^, <, > 分别是居中、左对齐、右对齐,后面带宽度, : 号后面带填充的字符,只能是一个字符,不指定则默认是用空格填充。
+ 表示在正数前显示 +,负数前显示 -; (空格)表示在正数前加空格
b、d、o、x 分别是二进制、十进制、八进制、十六进制。
此外我们可以使用大括号 {} 来转义大括号,如下实例:
在Python 3.6中引入 了f-strings,不仅比str.format使用简单,而且效率更高。
name='scott'
age=11
#{}中直接使用变量
print(f'My name is {name},My age is {age}')
#{}中运行表达式
print(f'{1**2+2**2+3**2}')
#调用Python内置函数
print(f'{name.upper()}')
#用lambda匿名函数:可以做复杂的数值计算
fun = lambda x : x+1
print(f'{fun(age)}')
6.dict用法
1) 使用key查找单个值
dict1 = {'name': 'Jhon', 'age': 23, 'love': 'C++'}
print(dict1['age']) # 使用键查找值
返回结果:23
2) 使用get()方法查找key对应的值
dict1 = {'name': 'Jhon', 'age': 23, 'love': 'C++'}
# 利用get函数使用key查找值,如果key存在返回value
print(dict1.get('age')) #23
# 利用get函数使用key查找值,如果key不存在返回None
print(dict1.get('age')) #None
# 利用get函数使用key查找值,如果key存在返回value, 如果key不存在返回指定值XXX
print(dict1.get('age2', 'XXX')) # XXX
3) 使用setdefault()查找
setdefault和get函数差不多,当key不存在,则查找的内容当做key放入dict,并设置默认值,设置为None
dict1 = {'name': 'Jhon', 'age': 23, 'love': 'C++'}
print(dict1.setdefault('age2'))
age2不存在,返回None
4) 查询所有键和值以及键值对
dict1 = {'name': 'Jhon', 'age': 23, 'love': 'C++'}
# keys() # 获取所有的键,返回列表
print(dict1.keys())
# values() # 获取所有的值,返回列表
print(dict1.values())
# items() # 获取所有键值对,返回元祖组成的列表
print(dict1.items())
5) 判断是否为有效dict
def getDictKey(myDict, value):
if not isinstance(myDict, dict): # 判断是否为dict
return False
keyList = []
for k, v in myDict.items():
if v == value:
keyList.append(k)
return keyList
d = "{'中国':'北京', '首都':'北京', '山东':'济南', '余额': 99.99}"
print("getDictKey(d, '北京')=", getDictKey(d, '北京'))
# output:
getDictKey(d, '北京')= False
7. itertools模块chain遍历
使用chain模块遍历多个可迭代对象。
from itertools import chain
chain(*iterables)
将多个可迭代对象进行合并,相当于如下代码:
def chain(*iterables):
# chain('XYZ', 'DEF') --> X Y Z D E F
for it in iterables:
for element in it:
yield element
############ ex.01
ops={}
ops['missing'] = ['gx_mean','gy_mean']
ops['collinear'] = ['gx_skew','gy_skew',]
ops['zero_importance'] = ['gx_kurt','gy_kurt']
ops['low_importance'] = ['gx_range','gy_range']
from itertools import chain
all_identified = set(list(chain(*list(ops.values()))))
all_identified
Out[112]:
{'gx_kurt',
'gx_mean',
'gx_range',
'gx_skew',
'gy_kurt',
'gy_mean',
'gy_range',
'gy_skew'}
ops['missing'] = ['gx_mean','gy_mean','gz_mean','ax_mean','ay_mean','az_mean',
'gx_std','gy_std','gz_std','ax_std','ay_std','az_std']
8.增强型赋值
增强型赋值语句是经常被使用到的,因为从各种学习渠道中,我们能够得知 i += 1 的效率往往要比 i = i + 1 更高一些(这里以 += 为例,实际上增强型赋值语句不仅限于此)。所以我们会乐此不疲的在任何能够替换普通赋值语句的地方使用增量型赋值语句,以此来优化代码。那么我们是否有想过,在什么情况下 i += 1 其实并不等效于 i = i + 1 !!
例一:使用增强型赋值语句:
In [1]: a = [1, 2, 3]
In [2]: b = a
In [3]: b += [1, 2, 3]
In [4]: print a, b
[1, 2, 3, 1, 2, 3] [1, 2, 3, 1, 2, 3]
In [5]: id(a), id(b)
Out[5]: (140213762276096, 140213762276096)
例二:使用普通赋值语句:
In [6]: a = [1, 2, 3]
In [7]: b = a
In [8]: b = b + [1, 2, 3]
In [9]: print a, b
[1, 2, 3] [1, 2, 3, 1, 2, 3]
In [10]: id(a), id(b)
Out[10]: (140213762466232, 140213762276168)
上述两个例子中,将一个列表类型对象赋值给变量 a,再将变量 a 赋值给变量 b,此时 a、b 指向了同一个内存对象 [1, 2, 3]。然后分别应用增量赋值运算符和普通赋值运算符来操作变量 b。从最后的结果来看,例一中的 a、b 在进行运算后依旧指向了同一个内存对象。例二则相反,a、b 分别指向了不同的内存对象,也就是说在例二中隐式的新建了一个内存对象。
这是一个值得注意的坑,警惕我们在使用增量赋值运算符来操作可变对象(如:列表)时可能会产生不可预测的结果。
要解释这个问题,首先需要了解「Python 共享引用」的概念:在 Python 中,允许若干个不同的变量引用指向同一个内存对象。同时在前文中也提到,增强赋值语句比普通赋值语句的效率更高,这是因为在 Python 源码中, 增强赋值比普通赋值多实现了“写回”的功能,也就是说增强赋值在条件符合的情况下(例如:操作数是一个可变类型对象)会以追加的方式来进行处理,而普通赋值则会以新建的方式进行处理。这一特点导致了增强赋值语句中的变量对象始终只有一个,Python 解析器解析该语句时不会额外创建出新的内存对象。所以例一中变量 a、b 的引用在最后依旧指向了同一个内存对象;相反,对于普通赋值运算语句,Python 解析器无法分辨语句中的两个同名变量(例如:b = b + 1)是否应该为同一内存对象,所以干脆再创建出一个新的内存对象用来存放最后的运算结果,所以例二中的 a、b 从原来指向同一内存对象,到最后分别指向了两个不同的内存对象。
这是一个不为人所熟知的问题,我们能得到的结论就是:尽量不要使用增量赋值运算符来处理任何可变类型对象,除非你对上述问题有了足够的了解。