一、语法糖的概念
“糖”,可以理解为简单、简洁,“语法糖”使我们可以更加简洁、快速的实现这些功能。 只是Python解释器会把这些特定格式的语法翻译成原本那样复杂的代码逻辑
我们使用的语法糖有:
- if...else 三元表达式: 可以简化分支判断语句,如 x = y.lower() if isinstance(y, str) else y
- with语句: 用于文件操作时,可以帮我们自动关闭文件对象,使代码变得简洁;
- 装饰器: 可以在不改变函数代码及函数调用方式的前提下,为函数增加增强性功能;
- 列表生成式: 用于生成一个新的列表
- 生成器: 用于“惰性”地生成一个无限序列
生成器表达式、列表解析式对比
列表解析式 在需要改变列表而不是需要新建某列表时,可以使用列表解析无返回值
-
>>> L= [(x+1,y+1) for x in range(3) for y in range(5)]
-
>>> L
-
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5)]
-
>>> N=[x+10 for x in range(10) if x>5]
-
>>> N
-
[16, 17, 18, 19]
生成器表达式 有返回值
当序列过长, 而每次只需要获取一个元素时,应当考虑使用生成器表达式而不是列表解析。生成器表达式的语法和列表解析一样,只不过生成器表达式是被()括起来的,而不是[],如下:
-
>>> L= (i + 1 for i in range(10) if i % 2)
-
>>> L
-
<generator object <genexpr> at 0xb749a52c>
-
>>> L1=[]
-
>>> for i in L:
-
... L1.append(i)
-
...
-
>>> L1
-
[2, 4, 6, 8, 10]
1. 当需要只是执行一个循环的时候尽量使用循环而不是列表解析,这样更符合python提倡的直观性。
-
for item in sequence:
-
process(item)
2. 当有内建的操作或者类型能够以更直接的方式实现的,不要使用列表解析。例如复制一个列表时,使用:L1=list(L)即可,不必使用:
L1=[x for x in L]
3.如果需要对每个元素都调用并且返回结果时,应使用L1=map(f,L), 而不是 L1=[f(x) for x in L]
对比:
计算方式
生成器表达式延迟计算,列表解析式立即计算
内存占用
从返回值来说,生成器省内存,列表解析式返回新的列表
生成器没有数据,内存占用极少,但是使用的时候,虽然一个个返回数据,但是合起来占用的内存也差不多
列表解析式构造新的列表需要占用内存
计算速度
单看计算时间,生成器表达式耗时非常短,列表解析式耗时长
但是生成器本身并没有返回任何值,只返回了一个生成器对象
列表解析式构造并返回了一个新的列表
-
要求:列出1~10中大于等于4的数字的平方
-
####################################################
-
1、普通方法:
-
>>> L = []
-
>>> for i in range(1,11):
-
... if i >= 4:
-
... L.append(i**2)
-
...
-
>>> print L
-
[16, 25, 36, 49, 64, 81, 100]
-
####################################################
-
2、列表解析
-
>>>L = [ i**2 for i in range(1,11) if i >= 4 ]
-
>>>print L
-
[16, 25, 36, 49, 64, 81, 100]
- <code class="language-python">要求:列出1~10所有数字的平方除以2的值
- ####################################################
- 1、普通方法
- >>> L = []
- >>> for i in range(1,11):
- ... L.append(i**2/2)
- ...
- >>> print L
- [0, 2, 4, 8, 12, 18, 24, 32, 40, 50]
- ####################################################
- 2、列表解析
- >>> L = [i**2/2 for i in range(1,11) ]
- >>> print L
- [0, 2, 4, 8, 12, 18, 24, 32, 40, 50]</code>
-
要求:列出1~10所有数字的平方除以2的值
-
####################################################
-
1、普通方法
-
>>> L = []
-
>>> for i in range(1,11):
-
... L.append(i**2/2)
-
...
-
>>> print L
-
[0, 2, 4, 8, 12, 18, 24, 32, 40, 50]
-
####################################################
-
2、列表解析
-
>>> L = [i**2/2 for i in range(1,11) ]
-
>>> print L
-
[0, 2, 4, 8, 12, 18, 24, 32, 40, 50]
-
要求:列出"/var/log"中所有已'.log'结尾的文件
-
##################################################
-
1、普通方法
-
>>>import os
-
>>>file = []
-
>>> for file in os.listdir('/var/log'):
-
... if file.endswith('.log'):
-
... file.append(file)
-
...
-
>>> print file
-
['anaconda.ifcfg.log', 'Xorg.0.log', 'anaconda.storage.log', 'Xorg.9.log', 'yum.log', 'anaconda.log', 'dracut.log', 'pm-powersave.log', 'anaconda.yum.log', 'wpa_supplicant.log', 'boot.log', 'spice-vdagent.log', 'anaconda.program.log']
-
##################################################
-
2.列表解析
-
>>> import os
-
>>> file = [ file for file in os.listdir('/var/log') if file.endswith('.log') ]
-
>>> print file
-
['anaconda.ifcfg.log', 'Xorg.0.log', 'anaconda.storage.log', 'Xorg.9.log', 'yum.log', 'anaconda.log', 'dracut.log', 'pm-powersave.log', 'anaconda.yum.log', 'wpa_supplicant.log', 'boot.log', 'spice-vdagent.log', 'anaconda.program.log']
-
要求:实现两个列表中的元素逐一配对。
-
1、普通方法:
-
>>> L1 = ['x','y','z']
-
>>> L2 = [1,2,3]
-
>>> L3 = []
-
>>> for a in L1:
-
... for b in L2:
-
... L3.append((a,b))
-
...
-
>>> print L3
-
[('x', 1), ('x', 2), ('x', 3), ('y', 1), ('y', 2), ('y', 3), ('z', 1), ('z', 2), ('z', 3)]
-
####################################################
-
2、列表解析:
-
>>> L1 = ['x','y','z']
-
>>> L2 = [1,2,3]
-
L3 = [ (a,b) for a in L1 for b in L2 ]
-
>>> print L3
-
[('x', 1), ('x', 2), ('x', 3), ('y', 1), ('y', 2), ('y', 3), ('z', 1), ('z', 2), ('z', 3)]
-
1 使用列表解析生成 9*9 乘法表
-
2
-
3 print('\n'.join([''.join(['%s*%s=%-2s '%(y,x,x*y)for y in range(1,x+1)])for x in range(1,10)]))
说明:以上实例,使用列表解析比使用普通方法的速度几乎可以快1倍。因此推荐使用列表解析。
列表生成式与map()、filter()等高阶函数功能对比
- <code class="language-python">要求:把一个列表中所有的字符串转换成小写,非字符串元素原样保留
- L = ['TOM', 'Peter', 10, 'Jerry']
- # 用列表生成式实现
- list1 = [x.lower() if isinstance(x, str) else x for x in L]
- # 用map()函数实现
- list2 = list(map(lambda x: x.lower() if isinstance(x, str) else x, L))</code>
-
要求:把一个列表中所有的字符串转换成小写,非字符串元素原样保留
-
L = ['TOM', 'Peter', 10, 'Jerry']
-
# 用列表生成式实现
-
list1 = [x.lower() if isinstance(x, str) else x for x in L]
-
-
# 用map()函数实现
-
list2 = list(map(lambda x: x.lower() if isinstance(x, str) else x, L))
- <code class="language-python">要求:把一个列表中所有的字符串转换成小写,非字符串元素移除
- L = ['TOM', 'Peter', 10, 'Jerry']
- # 用列表生成式实现
- list3 = [x.lower() for x in L if isinstance(x, str)]
- # 用map()和filter()函数实现
- list4 = list(map(lambda x: x.lower(), filter(lambda x: isinstance(x, str), L)))</code>
-
要求:把一个列表中所有的字符串转换成小写,非字符串元素移除
-
L = ['TOM', 'Peter', 10, 'Jerry']
-
# 用列表生成式实现
-
list3 = [x.lower() for x in L if isinstance(x, str)]
-
-
# 用map()和filter()函数实现
-
list4 = list(map(lambda x: x.lower(), filter(lambda x: isinstance(x, str), L)))
生成器(Generator)
1. 生成器的作用
按照某种算法不断生成新的数据,直到满足某一个指定的条件结束。
2. 生成器的构造方式
构造生成器的两种方式:
- 使用类似列表生成式的方式生成 (2*n + 1 for n in range(3, 11))
- 使用包含yield的函数来生成
如果计算过程比较简单,可以直接把列表生成式改成generator;但是,如果计算过程比较复杂,就只能通过包含yield的函数来构造generator。
-
# 使用类似列表生成式的方式构造生成器
-
g1 = (2*n + 1 for n in range(3, 6))
-
-
# 使用包含yield的函数构造生成器
-
def my_range(start, end):
-
for n in range(start, end):
-
yield 2*n + 1
-
-
g2 = my_range(3, 6)
-
print(type(g1))
-
print(type(g2))
-
输出结果:
-
-
<class 'generator'>
-
<class 'generator'>
既然通过列表生成式就可以直接创建一个新的list,那么为什么还要有生成器存在呢?
生成器中的元素是按照指定的算法推算出来的,只有调用时才生成相应的数据。这样就不必一次性地把所有数据都生成,从而节省了大量的内存空间,这使得其生成的元素个数几乎是没有限制的,并且操作的返回时间也是非常快速的(仅仅是创建一个变量而已)
生成器 VS 列表推导式
列表推导式是一次性创建所有数据的,而生成器是生成对象,需要我们调用next
方法逐一获取元素。假设我创建的数据很大很大(比如一千万),列表推导式会一次性创建,需要分配很大的内存空间存放这一千万数据,而生成器不会,只是创建了一个生成器对象,所以生成器更节省内存。
可迭代对象(Iterable)
可直接用于for循环的对象统称为可迭代对象(Iterable)
我们已经知道的可迭代(可用于for循环)的数据类型有:
- 集合数据类型:如list、tuple、dict、set、str等
- 生成器(Generator)
迭代器(Iterator)
Python中的Iterator对象表示的是一个数据流,Iterator可以被next()函数调用被不断返回下一个数据,直到没有数据可以返回时抛出StopIteration
异常错误
Iterable、Iterator与Generator之间的关系
生成器对象既是可迭代对象,也是迭代器
迭代器对象一定是可迭代对象,反之则不一定: 例如list、dict、str等集合数据类型是可迭代对象,但不是迭代器,但是它们可以通过iter()函数生成一个迭代器对象
也就是说:迭代器、生成器和可迭代对象都可以用for循环去迭代,生成器和迭代器还可以被next()方函数调用并返回下一个值。
字典解析
字典的形式是: {key: val},所以字典解析式也是用花括号括起来的
-
# 快速生成值是键二倍的字典
-
ndict = {x: x*2 for x in range(5)}
-
print ndict
-
{0: 0, 1: 2, 2: 4, 3: 6, 4: 8}
集合解析
python中集合也是用花括号括起来的,所以集合解析式: {x for x in iter}
-
# 快速生成1-10的集合
-
nset = {x for x in range(1, 11)}
-
print nset
-
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
---------------------
本文来自 努力一点点坚持一点点 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/sinat_23880167/article/details/78906819?utm_source=copy
(转)python高级:列表解析和生成表达式的更多相关文章
-
Python 的列表解析和生成表达式的异同
Python中的列表解析和生成表达式是非常好的特性,他们的形式相似,但是应用场景不太一样. 相似点 列表解析和生成表达式最大的相似点是使用形式: [expr for iter_var in ite ...
-
python 中的列表解析和生成表达式 - 转
优雅.清晰和务实都是python的核心价值观,如果想通过操作和处理一个序列(或其他的可迭代对象)来创建一个新的列表时可以使用列表解析( List comprehensions)和生成表达式,通过这两 ...
-
Python中的列表解析和生成表达式
摘要:优雅.清晰和务实都是python的核心价值观,如果想通过操作和处理一个序列(或其他的可迭代对象)来创建一个新的列表时可以使用列表解析( List comprehensions)和生成表达式,通过 ...
-
Python全栈day18(三元运算,列表解析,生成器表达式)
一,什么是生成器 可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他数据类型需要调用自己内置的__iter__方法),所以生成器是可迭代对象. 二,生成器分类在python中的表现形式 1 ...
-
Python基础(9)三元表达式、列表解析、生成器表达式
一.三元表达式 三元运算,是对简单的条件语句的缩写. # if条件语句 if x > f: print(x) else: print(y) # 条件成立左边,不成立右边 x if x > ...
-
Python列表解析与生成器表达式
Python列表解析 l = ["egg%s" %i for i in range(100) if i > 50] print(l) l= [1,2,3,4] s = 'he ...
-
Python自动化运维之7、生成器、迭代器、列表解析、迭代器表达式
迭代器和生成器 1.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外 ...
-
Python中的列表解析和生成器表达式
Python中的列表解析和生成器表达式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.列表解析案例 #!/usr/bin/env python #_*_coding:utf-8 ...
-
python的迭代器、生成器、三元运算、列表解析、生成器表达式
一 迭代的概念 迭代是Python最强大的功能之一,是访问集合元素的一种方式. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前 ...
随机推荐
-
Maven简单介绍
Maven是基于项目对象模型,可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具. Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具.由于 Maven 的缺省构建规则 ...
-
Excel表格常用的函数,留着备用
1. vlookup(lookup_value, table_array, col_index_num, boolean) -- 查找匹配函数 lookup_value: 你要去匹配的值 table_ ...
-
ASP.NET 如何发现问题的方法
1.打开IntelliTrace,查看遇到的问题: 2.打开IE8以上,按F12,启动js调试,查看遇到的错误:
-
js中json与数组字符串的相互转化
<SCRIPT LANGUAGE="JavaScript"> var t="{'firstName': 'cyra', 'lastName': 'richar ...
-
PHP之文件的锁定、上传与下载
小结文件的锁定机制.上传和下载 1.文件锁定 现在都在讲究什么分布式.并发等,实际上文件的操作也是并发的,在网络环境下,多个用户在同一时刻访问页面,对同一服务器上的同一文件进行着读取,如果,这个用户刚 ...
-
关于Asp.Net中避免用户连续多次点击按钮,重复提交表单的处理
Web页面中经常碰到这类问题,就是客户端多次点击一个按钮或者链接,导致程序出现不可预知的麻烦. 客户就是上帝,他们也不是有意要给你的系统造成破坏,这么做的原因很大一部分是因为网络慢,点击一个操作之后, ...
-
UVa 474 - Heads / Tails Probability
题目:计算1/(2^n)的值的前4为有效数字以及位数. 分析:数论,大整数.直接用数组模拟就可以. 说明:打表计算.查询输出. #include <iostream> #include & ...
-
6-使用requests库封装类处理get/post请求
1.request安装 1)pip安装,直接pip install requests 2)下载离线包安装,加压后,命令行进入路径,执行python setup.py install 2.创建工程 注意 ...
-
汽车之家店铺数据抓取 DotnetSpider实战
一.背景 春节也不能闲着,一直想学一下爬虫怎么玩,网上搜了一大堆,大多都是Python的,大家也比较活跃,文章也比较多,找了一圈,发现园子里面有个大神开发了一个DotNetSpider的开源库,很值得 ...
-
ZH奶酪:Ubuntu客户端通过SSH方式远程登录Ubuntu服务器
1.概述 传统的远程登录(telnet,rlogin)时不安全的,他们在网络上用明文传输口令和数据,SSH则是安全的,openssh提供两种级别的验证方式. (1)基于口令的安全验证:知道服务器的帐号 ...