python中关于for循环的碎碎念


Posted in Python onJune 30, 2017

为什么要挑战自己在代码里不写for loop?因为这样可以迫使你去使用比较高级、地道的语法或库。文中以python为例子,讲了不少大家其实在别人的代码里都见过、但自己很少用的语法。

这是一个挑战。我要你避免在任何情况下写for循环。同样的,我也要你找到一种场景——除了用for循环以外,用其他方法写都太难。请分享你的发现,我非常想听到这些

距离我开始探索超棒的Python语言特性已经有一段时间了。一开始,这只是我给自己的一个挑战,练习使用更多的语言特性来替代我从其他编程语言那里所学到的。但是事情渐渐变得更有趣了!代码不止变得更简短整洁,而且看起来更加结构化和有规律,在这篇文章中我将更多地介绍这些好处。

首先,让我们退一步看看在写一个for循环背后的直觉是什么:

1.遍历一个序列提取出一些信息

2.从当前的序列中生成另外的序列

3.写for循环已经是我的第二天性了,因为我是一个程序员

幸运的是,Python里面已经有很棒的工具帮你达到这些目标!你需要做的只是转变思想,用不同的角度看问题。

不到处写for循环你将会获得什么

1.更少的代码行数

2.更好的代码阅读性

3.只将缩进用于管理代码文本

Let's see the code skeleton below:

看看下面这段代码的构架:

# 1
with ...:
  for ...:
    if ...:
      try:
      except:
    else:

这个例子使用了多层嵌套的代码,这是非常难以阅读的。我在这段代码中发现它无差别使用缩进把管理逻辑(with, try-except)和业务逻辑(for, if)混在一起。如果你遵守只对管理逻辑使用缩进的规范,那么核心业务逻辑应该立刻脱离出来。

“扁平结构比嵌套结构更好” ? 《Python之禅》

为了避免for循环,你可以使用这些工具

1. 列表解析/生成器表达式

看一个简单的例子,这个例子主要是根据一个已经存在的序列编译一个新序列:

result = []
for item in item_list:
  new_item = do_something_with(item)
  result.append(item)

如果你喜欢MapReduce,那你可以使用map,或者Python的列表解析:

result = [do_something_with(item) for item in item_list]

同样的,如果你只是想要获取一个迭代器,你可以使用语法几乎相通的生成器表达式。(你怎么能不爱上Python的一致性?)

result = (do_something_with(item) for item in item_list)

2. 函数

站在更高阶、更函数化的变成方式考虑一下,如果你想映射一个序列到另一个序列,直接调用map函数。(也可用列表解析来替代。)

doubled_list = map(lambda x: x * 2, old_list)

如果你想使一个序列减少到一个元素,使用reduce

from functools import reduce
summation = reduce(lambda x, y: x + y, numbers)

另外,Python中大量的内嵌功能可/会(我不知道这是好事还是坏事,你选一个,不加这个句子有点难懂)消耗迭代器:

>>> a = list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> all(a)
False
>>> any(a)
True
>>> max(a)
9
>>> min(a)
0
>>> list(filter(bool, a))
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> set(a)
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> dict(zip(a,a))
{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}
>>> sorted(a, reverse=True)
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> str(a)
'[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'
>>> sum(a)
45

3. 抽取函数或者表达式

上面的两种方法很好地处理了较为简单的逻辑,那更复杂的逻辑怎么办呢?作为一个程序员,我们会把困难的事情抽象成函数,这种方式也可以用在这里。如果你写下了这种代码:

results = []
for item in item_list:
  # setups
  # condition
  # processing
  # calculation
  results.append(result)

显然你赋予了一段代码太多的责任。为了改进,我建议你这样做:

def process_item(item):
  # setups
  # condition
  # processing
  # calculation
  return result

results = [process_item(item) for item in item_list]

嵌套的for循环怎么样?

results = []
for i in range(10):
  for j in range(i):
    results.append((i, j))

列表解析可以帮助你:

results = [(i, j)
      for i in range(10)
      for j in range(i)]

如果你要保存很多的内部状态怎么办呢?

# finding the max prior to the current item
a = [3, 4, 6, 2, 1, 9, 0, 7, 5, 8]
results = []
current_max = 0
for i in a:
  current_max = max(i, current_max)
  results.append(current_max)

# results = [3, 4, 6, 6, 6, 9, 9, 9, 9, 9]

让我们提取一个表达式来实现这些:

def max_generator(numbers):
  current_max = 0
  for i in numbers:
    current_max = max(i, current_max)
    yield current_max

a = [3, 4, 6, 2, 1, 9, 0, 7, 5, 8]
results = list(max_generator(a))

“等等,你刚刚在那个函数的表达式中使用了一个for循环,这是欺骗!”

好吧,自作聪明的家伙,试试下面的这个。

4. 你自己不要写for循环,itertools会为你代劳

这个模块真是妙。我相信这个模块能覆盖80%你想写下for循环的时候。例如,上一个例子可以这样改写:

from itertools import accumulate
a = [3, 4, 6, 2, 1, 9, 0, 7, 5, 8]
resutls = list(accumulate(a, max))

另外,如果你在迭代组合的序列,还有product(),permutations(),combinations()可以用。

结论

1.大多数情况下是不需要写for循环的。

2.应该避免使用for循环,这样会使得代码有更好的阅读性。

行动

1.再看一遍你的代码,找出任何以前凭直觉写下for循环的地方,再次思考一下,不用for循环再写一遍是不是有意义的。

2.分享你很难不使用for循环的例子。

Python 相关文章推荐
python用ConfigObj读写配置文件的实现代码
Mar 04 Python
简单介绍Python中的RSS处理
Apr 13 Python
详解Django框架中用context来解析模板的方法
Jul 20 Python
Python操作使用MySQL数据库的实例代码
May 25 Python
python2.7实现FTP文件下载功能
Apr 15 Python
pandas多级分组实现排序的方法
Apr 20 Python
Puppeteer使用示例详解
Jun 20 Python
Django实现auth模块下的登录注册与注销功能
Oct 10 Python
完美解决pycharm 不显示代码提示问题
Jun 02 Python
详解pandas.DataFrame.plot() 画图函数
Jun 14 Python
Python+unittest+requests 接口自动化测试框架搭建教程
Oct 09 Python
深入理解pytorch库的dockerfile
Jun 10 Python
Python实现的微信公众号群发图片与文本消息功能实例详解
Jun 30 #Python
python实现给微信公众号发送消息的方法
Jun 30 #Python
Python信息抽取之乱码解决办法
Jun 29 #Python
python urllib urlopen()对象方法/代理的补充说明
Jun 29 #Python
python笔记:mysql、redis操作方法
Jun 28 #Python
老生常谈Python序列化和反序列化
Jun 28 #Python
python flask实现分页效果
Jun 27 #Python
You might like
比较全面的PHP数组的使用方法小结
2010/09/23 PHP
smarty简单分页的实现方法
2014/10/27 PHP
ajax+php实现无刷新验证手机号的实例
2017/12/22 PHP
DIY jquery plugin - tabs标签切换实现代码
2010/12/11 Javascript
Extjs407 getValue()和getRawValue()区别介绍
2013/05/21 Javascript
jquery遍历之parent()和parents()的区别及parentsUntil()方法详解
2013/12/02 Javascript
JavaScript组合拼接字符串的效率对比测试
2014/11/06 Javascript
JS变量中有var定义和无var定义的区别以及es6中let命令和const命令
2017/02/19 Javascript
基于JavaScript实现活动倒计时效果
2017/04/20 Javascript
jQuery异步提交表单实例
2017/05/30 jQuery
nodejs模块学习之connect解析
2017/07/05 NodeJs
解决vue多个路由共用一个页面的问题
2018/03/12 Javascript
Vue-cli3项目配置Vue.config.js实战记录
2018/07/29 Javascript
vue 动态添加的路由页面刷新时失效的原因及解决方案
2021/02/26 Vue.js
[01:13:17]Secret vs NB 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[03:06]2018年度CS GO最具人气解说-完美盛典
2018/12/16 DOTA
[42:32]VP vs RNG 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.21.mp4
2020/07/19 DOTA
[01:02:00]DOTA2-DPC中国联赛 正赛 Elephant vs IG BO3 第三场 1月24日
2021/03/11 DOTA
Python模拟登录12306的方法
2014/12/30 Python
Python字符串逐字符或逐词反转方法
2015/05/21 Python
简单谈谈Python中函数的可变参数
2016/09/02 Python
Python做文本按行去重的实现方法
2016/10/19 Python
python利用标准库如何获取本地IP示例详解
2017/11/01 Python
python实现傅里叶级数展开的实现
2018/07/21 Python
django框架中间件原理与用法详解
2019/12/10 Python
tensorflow 保存模型和取出中间权重例子
2020/01/24 Python
python字符串,元组,列表,字典互转代码实例详解
2020/02/14 Python
婚庆公司的创业计划书
2014/01/22 职场文书
人事部岗位职责范本
2014/03/05 职场文书
初中国旗下的演讲稿
2014/08/28 职场文书
幼儿园教师师德师风演讲稿:我自豪我是一名幼师
2014/09/10 职场文书
对党的十八届四中全会的期盼
2014/10/17 职场文书
Windows中Redis安装配置流程并实现远程访问功能
2021/06/07 Redis
用Python爬取各大高校并可视化帮弟弟选大学,弟弟直呼牛X
2021/06/11 Python
Centos7中MySQL数据库使用mysqldump进行每日自动备份的编写
2021/08/02 MySQL
Win11 Build 25179预览版发布(附更新内容+ISO官方镜像下载)
2022/08/14 数码科技