python新手必躺的5大坑

对于Python新手来说,写代码很少考虑代码的效率和简洁性,因此容易造成代码冗长、执行慢,这些都是需要改进的地方。本文是想通过几个案列给新手一点启发,怎样写python代码更优雅。

新人躺坑之一:不喜欢使用高级数据结构

sets(集合)

很多新手忽视sets(集合)和tuple(元组)的强大之处

例如,取两个列表交集:

def common_elements(list1, list2):
common = []
for item1 in list1:
if item1 in list2:
common.append( item1 ) 、
return common

这样写会更好:

def common_elements(list1, list2):
common = set(list1).intersection(set(list2))
return list(common)

dic(字典)

新手枚举(访问和取出)字典的键和对应值,认为对应值必须通过键来访问,往往会这样做:

my_dict = {'a':1,'b':2}
for key in my_dict:
print(key, my_dict[key])

有一个更优雅的方法可以实现:

my_dict = {'a':1,'b':2}
for key, value in my_dict.items():
print(key, value)

对大部分项目来说,这样写会更加有效率。

tuple(元组)

元组一旦创建就无法更改元素,看似没有什么用处,其实元组的作用大着呢!很多函数方法都会返回元组,比如enumerate()dict.items(),并且可以在函数中使用元组,返回多个值。还能够很方便地从元组中提取信息:

a,b = ('cat','dog')

上面元组中有两个元素,分别被赋给a,b。如果有多个值,同样可以提取:

a,b,c = ('cat','dog','tiger')
print(a,b,c)

提取首、尾两个元素:

first,*_,end = (1,2,3,4,5,6)
print(first,end)
# 输出:1、6

提取首、中、尾三部分:

first,*middle,end = (1,2,3,4,5,6)
print(first,middle,end)
# 输出:1、[2, 3, 4, 5]、6

元组还可以用来交换变量:

(a,b,c) = (c,a,b)

上面a变成之前的c,b变成之前的a,c变成之前的b

元组也能作为字典的键,所以如果你需要存储数据,可以使用带有元组键的字典,比如说经纬度数据。

新人躺坑之二:不喜欢使用上下文管理器

新手可能会习惯这样进行读取文件操作:

if os.path.exists(data_file_path):
data_file = open(data_file_path,'r')
else:
raise OSERROR
print( data_file.read())
data.close()

这样写会有几个明显的问题:

  • 可能出现文件存在,但文件被占用,无法读取的情况
  • 可能出现文件可以被读取,但操作文件对象出现报错的情况
  • 可能出现忘记关闭文件的情况

如果使用with...语句,问题就迎刃而解了:

with open(data_file_path,'r') as data_file:
print(data_file.read)

这样可以捕获任何打开文件或处理数据时的异常情况,并且在任务处理完后自动关闭文件。

python初学者可能不太了解上下文管理器的神奇之处,它真的能带来巨大的便利。

更多关于python文件读写和上下文管理器的使用,可以看下面的文章

新人躺坑之三:不喜欢使用标准库

标准库itertoolscollections仍然很少被初学者使用

itertools

如果你看到下面的任务:

list1 = range(1,10)
list2 = range(10,20)
for item1 in list1:
for item2 in list1:
print(item1*item2)

这是一个嵌套循环操作,为提高代码效率,完全可以用product()函数替代嵌套循环:

from itertools import product
list1 = range(1,10)
list2 = range(10,20)
for item1,item2 in product(list1, list2):
print(item1*item2)

这两段代码的结果完全一样,但使用标准库函数明显更加简洁高效。itertools还有很多方便操作迭代对象的函数,比如:

  • count()函数会创建一个无限迭代器
  • cycle()函数会把传入的序列无限重复下去
  • chain()可以把多个迭代对象串联起来
  • group()函数可以把迭代其中相邻的重复元素挑出来,放在一起
  • ......

    有兴趣可以详细看看itertools库的各种神奇函数

collections

新手对python集合模块了解的可能并不多,你可能会遇到这样的情形:

consolidated_list = [('a',1),('b',2),('c',3),('b',4)]
items_by_id = {}
for id_, item in consolidated_list:
if id_ not in items_by_id:
items_by_id[id_] = []
if id_ in items_by_id:
items_by_id[id_].append(item)

上面代码构建了一个字典,依次向字典中添加信息,如果某个键已经存在,则以某种方式修改该键的值;如果某个键不存在,则添加对应键值对。

这种算法非常常见,你可以用collects模块的defaultdict()函数来实现同样效果:

from collections import defaultdict

items_by_id = defaultdict(list)
consolidated_list = [('a',1),('b',2),('c',3),('b',4)] for id_, item in consolidated_list:
items_by_id[id_].append(item)

在此列中,defaultdict()接受一个list作为参数,当键不存在时,则返回一个空列表作为对应值。

有时候我们会遇到统计词频的案例,比如:

# 统计词频
colors = ['red', 'blue', 'red', 'green', 'blue', 'blue']
result = {}
for color in colors:
if result.get(color)==None:
result[color]=1
else:
result[color]+=1
print (result)
# 输出 {'red': 2, 'blue': 3, 'green': 1}

完全可以用defaultdict()函数实现上面的计数功能:

colors = ['red', 'blue', 'red', 'green', 'blue', 'blue']
d = defaultdict(int)
for color in colors:
d[color] += 1
print(d)

更简单的方法用collections模块的Counter()函数:

from collections import Counter
colors = ['red', 'blue', 'red', 'green', 'blue', 'blue']
c = Counter(colors)
print (dict(c))

对于备份文件,新人往往会用system模块:

from  os import system
system("xcopy e:\\sample.csv e:\\newfile\\")

其实shutil模块更好用:

import shutil
shutil.copyfile('E:\\q.csv', 'e:\\movie\\q.csv')

因为shutil会很详细地报告错误和异常。

新人躺坑之四:不喜欢使用异常处理

无论老手新手都应该在写代码的时候进行异常处理操作,这样可以使代码更加健壮。异常处理一般会用try...except语句,具体使用方法可见:

新人躺坑之五:不喜欢使用生成器

除非你的list十分复杂,并且频繁调用,否则都建议使用生成器,因为它非常节省内存,举个例子:

def powers_of_two(max=20000):
i = 0
powers = []
while 2**i < max:
powers.append[2**i]
i += 1
return powers

对于使用次数少、占据大量内存、且容易生成的数据,可以用生成器替代列表存储:

from itertools import count, takewhile
def powers_of_two(max=20000):
for index in takewhile(lambda i: 2**i < max, count(start=0)):
yield 2**index

更多关于生成器的内容,请见:

python新手必躺的5大坑的更多相关文章

  1. 【python】python新手必碰到的问题---encode与decode,中文乱码[转]

    转自:http://blog.csdn.net/a921800467b/article/details/8579510 为什么会报错“UnicodeEncodeError:'ascii' codec ...

  2. [转]python新手必碰到的问题---encode与decode,中文乱码--转载

    edu.codepub.com/2009/1029/17037.php 这个问题在python3.0里已经解决了. 这有篇很好的文章,可以明白这个问题: 为什么会报错“UnicodeEncodeErr ...

  3. (转)Python新手写出漂亮的爬虫代码2——从json获取信息

    https://blog.csdn.net/weixin_36604953/article/details/78592943 Python新手写出漂亮的爬虫代码2——从json获取信息好久没有写关于爬 ...

  4. (转)Python新手写出漂亮的爬虫代码1——从html获取信息

    https://blog.csdn.net/weixin_36604953/article/details/78156605 Python新手写出漂亮的爬虫代码1初到大数据学习圈子的同学可能对爬虫都有 ...

  5. Python 新手常犯错误

    Python 新手常犯错误(第二部分) 转发自:http://blog.jobbole.com/43826/ 作用域 在这篇文章里,我们来关注作用域在Python被误用的地方.通常,当我们定义了一个全 ...

  6. 新手必看】Highcharts的100个基础问答

    新手必看]Highcharts的100个基础问答 2014-12-2 10:59| 发布者: Mr.Zhang| 查看: 2749| 评论: 3|来自: Highcharts中文论坛   摘要: 1. ...

  7. Node.js新手必须知道的4个JavaScript概念

    如果只需要知道一种编程语言就可以构建一个全栈的应用程序,是不是特别了不起?Ryan Dahl为了把这个想法成为现实,创造了node.js.Node.js是建立在Chrome强劲的V8 JavaScri ...

  8. python新手上车001

    python新手上车001 一般建议: 1.下载:从https://www.python.org/downloads/windows/  python官网进行下载建议就从3.7.2开始吧(我从这个版本 ...

  9. Python新手学习raise用法

    当程序出现错误时,系统会自动引发异常.除此之外,Python也允许程序自行引发异常,自行引发异常使用 raise 语句来完成. 很多时候,系统是否要引发异常,可能需要根据应用的业务需求来决定,如果程序 ...

随机推荐

  1. js中的时间显示

    var approveTime; approveTime=new Date(da[i].approveTime).toLocaleDateString(); 结果是 xxxx年xx月xx日

  2. POJ 1236 Network of Schools —— (缩点的应用)

    题目大意:有N个学校和一些有向边将它们连结,求: 1.最少需要向几个学校发放软件,使得他们中的每一个学校最终都能够获得软件. 2.最少需要增加几条有向边使得可以从任意一个学校发放软件,使得每一个学校最 ...

  3. 去除ZERO WIDTH SPACE 零宽字符: 看不见却占位置的字符

    ZERO WIDTH SPACE 由于历史原因,编码方案中保留着该类编码 解决方案 1. 替换 ```js str.replace(/[\u200B-\u200D\uFEFF]/g, ''); ``` ...

  4. 手把手教你设置MongoDB密码

    mongodb密码和传统数据如mysql等有些区别: mongodb的用户名和密码是基于特定数据库的,而不是基于整个系统的.所有所有数据库db都需要设置密码. 1. 查看所有数据库(在mongodb新 ...

  5. SpringCloud-Config通过Java访问URL对敏感词加密解密

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

  6. linux下如何基于已有容器创建image并运行?

    1. 通过docker ps命令先找到容器id,示例如下,123456789012就是我们要找的 jello@~$ docker ps CONTAINER ID IMAGE COMMAND CREAT ...

  7. easyUI之ComboBox(下拉列表框)

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  8. input 表单

    1:datalist元素,一般与input组建配合使用,以定义可能输入的值,例如: <!DOCTYPE html> <html lang="en"> < ...

  9. Win10设置文件夹权限报错-(提示:无法枚举容器中的对象 访问被拒绝)

    一.右击文件 选择“属性”-“安全”-“高级”,如下图 二.查看哪个用户的权限是:“完全控制”,我这里是“SYSTEM”用户. 三.选择顶部的 “更改-“高级”-“立即查找”,然后选择管理员账户“SY ...

  10. eclipse下生成Java类图和时序图,生成UML图

    1.安装和使用AmaterasUML 安装AmaterasUML前,需要先安装GEF采用eclipse在线安装方式安装就好.eclipse在线安装GEF的地址:http://download.ecli ...