大家好,我是陈诚。今天分享Python的15个坏习惯,产生这些坏习惯的主要原因是开发者对Python的经验不足。摒弃这些习惯,用Pythonic的方式写代码,不仅可以提高代码质量,还可以给看代码的人留下好印象~1.使用+号拼接字符串的坏习惯:defmanual_str_formatting(name,subscribers):ifsubscribers>100000:print("Wow"+name+"!youhave"+str(subscribers)+"subscribers!")else:print("Lol"+name+"那不是manysubs")adjust最后一种方法是使用f-string,这样效率会更高:defmanual_str_formatting(name,subscribers):#betterifsubscribers>100000:print(f"Wow{name}!youhave{subscribers}subscribers!")else:print(f"Lol{name}that'snotmanysubs")2.使用finally而不是上下文管理器的坏习惯:deffinally_instead_of_context_manager(host,port):s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)try:s.connect((host,port))s.sendall(b'Hello,world')finally:s.close()调整后的做法是使用上下文管理器,即使一个except离子发生,套接字将被关闭::deffinally_instead_of_context_manager(host,port):#closeevenifexceptionwithsocket.socket(socket.AF_INET,socket.SOCK_STREAM)ass:s.connect((host,port))s.sendall(b'Hello,world')3.尝试手动关闭文件是不好的做法:defmanually_calling_close_on_a_file(filename):f=open(filename,"w")f.write("hello!\n")f.close()调整的方法是使用上下文管理器,即使发生异常,文件也会自动关闭,任何有上下文管理器的人都应该首先使用:defmanually_calling_close_on_a_file(filename):withopen(filename)asf:f.write("hello!\n")#closeautomatic,即使是exception4,除了Not什么都没有写不好的做法:defbare_except():whileTrue:try:s=input("Inputanumber:")x=int(s)breakexcept:#oops!can'tCTRL-Ctoexitprint("Notanumber,tryagain")将捕获所有异常,这样即使按下CTRL-C程序也不会终止。调整后的方法是defbare_except():whileTrue:try:s=input("Inputanumber:")x=int(s)breakexceptException:#比这个更好的是使用ValueErrorprint("Notanumber,再试一次”)5。函数参数使用变量对象如果函数参数使用变量对象,那么下面的错误做法defmutable_default_arguments():defappend(n,l=[]):l.append(n)returnll1=append(0)#[0]l2=append(1)#[0,1]调整后的方法如下:defmutable_default_arguments():defappend(n,l=None):iflisNone:l=[]l.append(n)returnll1=append(0)#[0]l2=append(1)#[1]6.切勿使用理解式错误做法squares={}foriinrange(10):squares[i]=i*iadjustedmethododd_squares={i:i*iforiinrange(10)}7.求导使用的上瘾式推导虽然好用,但不能牺牲可读性,不好的做法c=[sum(a[n*i+k]*b[n*k+j]forkinrange(n))foriinrange(n)forjinrange(n)]adjust最后的方法如下:c=[]foriinrange(n):forjinrange(n):ij_entry=sum(a[n*i+k]*b[n*k+j]forkinrange(n))c.append(ij_entry)8.用==判断单例是否是不好的做法defequality_for_singletons(x):ifx==None:passifx==True:passifx==False:afterpassadjustment做法如下如下:defequality_for_singletons(x):#betterifxisNone:passifxisTrue:passifxisFalse:pass9,usingaC-styleforloopbadpracticedefrange_len_pattern():a=[1,2,3]for我在范围内(len(a)):v=a[i]...b=[4,5,6]foriinrange(len(b)):av=a[i]bv=b[i]...调整后的做法如下:defrange_len_pattern():a=[1,2,3]#insteadforvina:...#或者如果你想要i,vine的索引numerate(a):...#而不是使用zipforav,bvinzip(a,b):...10,不实用dict.items坏习惯defnot_using_dict_items():d={"a":1,"b":2,"c":3}forkeyind:val=d[key]...调整后的做法如下:defnot_using_dict_items():d={"a":1,"b":2,"c":3}forkey,valind.items():...11.使用time.time()统计耗时的坏习惯deftiming_with_time():start=time.time()time.sleep(1)end=time.time()print(end-start)调整后的做法是使用time.perf_counter(),更准确:deftiming_with_time():#moreaccuratestart=time.perf_counter()time.sleep(1)end=time.perf_counter()print(end-start)12.使用打印代替记录日志。不好的做法defprint_vs_logging():print("debuginfo")print("justsomeinfo")print("baderror"),如下:defprint_vs_logging():#versus#inmainlevel=logging.DEBUGfmt='[%(levelname)s]%(asctime)s-%(message)s'logging.basicConfig(level=level,format=fmt)#whereverlogging.debug("调试信息")logging.info("只是一些信息")logging.error("uhoh:(")13.调用外部命令时使用shell=True错误做法subprocess.run(["ls-l"],capture_output=True,shell=True)如果shell=True,将ls-l传递给/bin/sh(shell)而不是Unix上的ls程序将导致子进程产生一个In换句话说,使用中间shell意味着命令字符串中的变量、glob模式和其他特殊shell功能在命令运行之前进行预处理。例如,在执行echo命令之前处理$HOME。处理。调整后的做法是拒绝从shell执行,如下:subprocess.run(["ls","-l"],capture_output=True)14.永远不要尝试使用numpyBadpracticedefnot_using_numpy_pandas():x=list(range(100))y=list(range(100))s=[a+bfora,binzip(x,y)]调整后的方法如下:importnumpyasnpdefnot_using_numpy_pandas():#PerformanceFasterx=np.arange(100)y=np.arange(100)s=x+y15,我喜欢import*adjustment的方式,如下:fromitertoolsimport*count()这样的话,没人知道这个脚本的结尾有很多变量,更好的方法:frommypackage.nearby_moduleimportawesome_functiondefmain():awesome_function()ifname=='__main__':main()以上是我总结的一些tips,到这里就结束了.小伙伴们有其他的补充或者不同的意见,欢迎在评论里讨论或者私信我~
