长假你在家做什么?宅在家里看电视剧,看跨年晚会;逛街、吃火锅、唱歌;学习Python别忘了,下面是老司机总结的一些干货技巧,很有价值,尤其是有其他语言相对于c/c++编程基础的朋友,记得收藏哦!1.混淆操作本节对比一些Python混淆操作。1.1有放回的随机抽样和无放回的随机抽样importrandomrandom.choices(seq,k=1)#listoflengthk,withreplacementsamplingrandom.sample(seq,k)#listoflengthk,nonePutbacksampling1.2Lambda函数参数func=lambday:x+y#函数运行时绑定x的值func=lambday,x=x:x+y#函数定义时绑定x的值1.3copy和deepcopyimportcopyy=copy.copy(x)#只复制最顶层y=copy.deepcopy(x)#复制所有嵌套的部分复制和变量别名结合使用时,很容易混淆:a=[1,2,[3,4]]#Alias.b_alias=aassertb_alias==aandb_aliasisa#Shallowcopy.b_shallow_copy=a[:]assertb_shallow_copy==aandb_shallow_copyisnotaandb_shallow_copy[2]isa[2]#深拷贝.importcopyb_deep_copy=copy.deepcopy(a)assertb_deep_copy==aandb_deep_copyisnotaandb_deep_copy[2]isnota[2]别名的修改会影响原变量,(浅)拷贝中的元素是原列表中元素的别名,深拷贝是递归拷贝的,深拷贝的修改不影响原变量。1.4==andisx==y#两个引用对象是否有相同的值xisy#两个引用是否指向同一个对象1.5判断类型type(a)==int#面向对象设计忽略多态特性isinstance(a,int)#考虑面向对象设计中的多态特性1.6字符串搜索str.find(sub,start=None,end=None);str.rfind(...)#如果没有找到,返回-1str.index(sub,start=None,end=None);str.rindex(...)#如果没有找到,会抛出ValueError异常如果你想从0开始到索引也可以用~。print(a[-1],a[-2],a[-3])print(a[~0],a[~1],a[~2])2.C/C++用户指南很多Python用户是从以前的C/C++迁移过来的。这两种语言在语法和代码风格上都有一些差异。本节简要介绍它们。2.1大数和小数C/C++的习惯是定义一个非常大的数,Python中有inf和-inf:a=float('inf')b=float('-inf')2.2Boolean的C/C++的习惯是用0和非零值来表示True和False,而Python建议直接用True和False来表示布尔值。a=Trueb=False2.3判断为nullC/C++有用if(a)和if(!a)判断空指针的习惯。Python对None的判断是:ifxisNone:pass如果使用ifnotx,其他对象(如长度为0的字符串、列表、元组、字典等)将被视为False。2.4交换值C/C++的习惯是定义一个临时变量来交换值。使用Python的Tuple操作,可以一步搞定。a,b=b,a2.5比较C/C++的习惯是使用两个条件。使用Python可以一步完成。if0out',shell=True).decode('utf-8')2.12Don'trepeatthewheel,don'trepeatMakingwheels,Python叫做batteriesincluded,意思是Python提供了很多常见问题的解决方案。3.常用工具3.1读写CSV文件importcsv#readandwritewithoutheaderwithopen(name,'rt',encoding='utf-8',newline='')asf:#newline=''letPythonnotUnifythenewlineprocessingforrowincsv.reader(f):print(row[0],row[1])#CSV读取的数据都是str类型withopen(name,mode='wt')asf:f_csv=csv.writer(f)f_csv.writerow(['symbol','change'])#readandwritewithheaderwithopen(name,mode='rt',newline='')asf:forcsv.DictReader(f)中的行:print(row['symbol'],row['change'])withopen(name,mode='wt')asf:header=['symbol','change']f_csv=csv.DictWriter(f,header)f_csv.writeheader()f_csv.writerow({'symbol':xx,'change':xx})注意当csv文件过大时会报错:_csv.Error:fieldlargerthanfieldlimit(131072),通过修改上限解决3.2itertoolsM中定义的迭代器工具任何迭代器工具,例如子序列工具:importitertoolsitertools.islice(iterable,start=None,stop,step=None)#islice('ABCDEF',2,None)->C,D,E,Fitertools.filterfalse(predictate,iterable)#过滤掉predicate为False的元素#filterfalse(lambdax:x<5,[1,4,6,4,1])->6itertools.takewhile(predicate,iterable)#当predicate为FalseStop迭代#takewhile(lambdax:x<5,[1,4,6,4,1])->1,4itertools.dropwhile(predicate,iterable)#当predicate为假时开始迭代#dropwhile(lambdax:x<5,[1,4,6,4,1])->6,4,1itertools.compress(iterable,selectors)#根据selectors的每个元素是True还是False进行选择#compress('ABCDEF',[1,0,1,0,1,1])->A,C,E,F序列排序:sorted(iterable,key=None,reverse=False)itertools.groupby(iterable,key=None)#按值分组,iterable需要先排序#groupby(sorted([1,4,6,4,1]))->(1,iter1),(4,iter4),(6,iter6)itertools.permutations(iterable,r=None)#排列,返回值为Tuple#permutations('ABCD',2)->AB,AC,AD,BA,BC,BD,CA,CB,CD,DA,DB,DCitertools.combinations(iterable,r=None)#组合,返回值为Tupleitertools.combinations_with_replacement(...)#combinations('ABCD',2)->AB,AC,AD,BC,BD,CD合并多个序列:itertools.chain(*iterables)#直接拼接多个序列#chain('ABC','DEF')->A,B,C,D,E,Fimportheapqheapq.merge(*iterables,key=None,reverse=False)#多个序列按顺序拼接#merge('ABF','CDE')->A,B,C,D,E,Fzip(*iterables)#最短序列用完就停止,结果只能消费一次itertools.zip_longest(*iterables,fillvalue=None)#最长序列用完就停止,结果只能被消费一次3.3计数器计数器可以统计一个可迭代对象中每个元素出现的次数importcollections#createcollections.Counter(iterable)#frequencycollections.Counter[key]#keyoccurrencefrequency#returnnoccurrences出现频率最高的元素及其对应的出现频率,如果n为None,则返回所有元素collections.Counter.most_common(n=None)#插入/更新collections.Counter.u更新(可迭代)counter1+counter2;counter1-counter2#counterplusMinus#检查两个字符串的组成元素是否相同将其设置为默认值。importcollectionscollections.defaultdict(type)#第一次访问dict[key]时,会不带参数调用type,给dict[key]提供初始值3.5OrderedDictimportcollectionscollections.OrderedDict(items=None)#迭代时保留原始插入序列4.高性能编程与调试4.1输出错误和警告信息到标准错误输出信息importsyssys.stderr.write('')输出警告信息importwarningswarnings.warn(message,category=UserWarning)#类别的值有DeprecationWarning,SyntaxWarning,RuntimeWarning,ResourceWarning,FutureWarning来控制警告信息的输出。$python-Wall#输出所有警告,相当于设置warnings.simplefilter('always')$python-Wignore#忽略所有警告,相当于设置warnings.simplefilter('ignore')$python-Werror#将所有的警告转为异常,相当于设置warnings.simplefilter('error')4.2在代码中测试有时候为了调试,我们想在代码中加入一些代码,通常一些打印语句可以写成:#indebug部分代码if__debug__:pass调试结束后,这部分代码会被忽略,在命令行执行-O选项:$python-0main.py4.3代码风格检查使用pylint可以做了大量的代码风格和语法检查,并且可以在运行pylintmain.py4.4代码之前发现一些错误耗时耗时测试$python-mcProfilemain.py测试一个代码块耗时#codeblock从contextlibimportcontextmanagerdefinefromtimeimportperf_counter@co时的消耗ntextmanagerdef时间块(标签l):tic=perf_counter()try:yieldfinally:toc=perf_counter()print('%s:%s'%(label,toc-tic))#代码块耗时测试withtimeblock('counting'):通行代码耗时优化的一些原则着重于优化出现性能瓶颈的地方,而不是避免在所有代码中使用全局变量。局部变量的查找比全局变量快,全局变量的代码定义通常在函数中运行快15%-30%。避免使用.访问属性。使用frommoduleimportname,将经常访问的类的成员变量self.member放入局部变量会更快。尽可能使用内置数据结构。str、list、set、dict等都是用C实现的,运行速度非常快。避免创建不必要的中间变量和copy.deepcopy()。字符串拼接,比如a+':'+b+':'+c会产生很多无用的中间变量,':',join([a,b,c])会效率高很多。此外,您需要考虑是否需要字符串连接。例如,print(':'.join([a,b,c]))的效率低于print(a,b,c,sep=':')。5.其他Python技巧5.1argmin和argmaxitems=[2,1,3,4]argmin=min(range(len(items)),key=items.__getitem__)argmax是一样的。5.2转置二维列表A=[['a11','a12'],['a21','a22'],['a31','a32']]A_transpose=list(zip(*A))#listoftupleA_transpose=list(list(col)forcolinzip(*A))#listoflist5.3一维列表扩展为二维列表A=[1,2,3,4,5,6]#首选.list(zip(*[iter(A)]*2))
