语法糖(Syntactic sugar),是由Peter J. Landin(和图灵一样的天才人物,是他最先发现了Lambda演算,由此而创立了函数式编程)创造的一个词语,它意指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜”的语法。语法糖往往给程序员提供了更实用的编码方式,有益于更好的编码风格,更易读。
在python语言中语法糖有三元表达式、列表生成式、列表生成器、迭代器等等,具体可参考如下博客:
https://segmentfault.com/a/1190000006261012
For constructing a list, a set or a dictionary Python provides special syntax called “displays”, each of them in two flavors:
为构造一个列表、集合或者字典,python提供了称谓”显式”的特殊语法,每种语法都有两种形式
1、either the container contents are listed explicitly
容器内容被明确列出(即普通常用的列表)
2、they are computed via a set of looping and filtering instructions, called a comprehension
它们通过一组循环和过滤指令来计算,称为生成式
Common syntax elements for comprehensions are:
语法格式如下:
comprehension ::= expression comp_for
comp_for ::= “for” target_list “in” or_test [comp_iter]
comp_iter ::= comp_for | comp_if
comp_if ::= “if” expression_nocond [comp_iter]
The comprehension consists of a single expression followed by at least one for clause and zero or more for or if clauses.
生成式是由单个表达式后紧跟至少一个for语句和多个或0个if语句
A list display is a possibly empty series of expressions enclosed in square brackets:
list_display ::= “[” [starred_list | comprehension] “]”
[expr for iter_var in iterable] 即 [返回值 for 元素 in 可迭代对象]
工作过程:
- 迭代iterable中的每个元素;
- 每次迭代都先把结构赋值给iter_var,然后通过exp得到一个新的返回值;
- 最后将返回值形成一个新的列表。
代码示范:
#!/bin/python3
#-*- coding: UTF-8 -*-
lst = [x*x for x in range(1,6)]
print(lst)
运行结果:
[1, 4, 9, 16, 25]
[expr for item in iterable if cond1 if cond2]
工作过程:
#!/bin/python3
#-*- coding: UTF-8 -*-
lst = [x for x in range(1,20) if x>=10 if x%2==0]
print(lst)
运行结果:
[10, 12, 14, 16, 18]
[expr for i in iterable1 for j in iterable2 ]
工作过程:
#!/bin/python3
#-*- coding: UTF-8 -*-
lst0 = [(x,y) for x in 'abc' for y in range(2)]
lst1 = [[x,y] for x in 'abc' for y in range(2)]
lst2 = [{x,y} for x in 'abc' for y in range(2)]
print(lst0)
print(lst1)
print(lst2)
运行结果:
[('a', 0), ('a', 1), ('b', 0), ('b', 1), ('c', 0), ('c', 1)]
[['a', 0], ['a', 1], ['b', 0], ['b', 1], ['c', 0], ['c', 1]]
[{
0, 'a'}, {
1, 'a'}, {
0, 'b'}, {
1, 'b'}, {
0, 'c'}, {
1, 'c'}]
代码示范:
#!/bin/python3
#-*- coding: UTF-8 -*-
lst = [x**2 for x in range(1,11)]
print(lst)
运行结果:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
生成新列表,要求新列表元素是lst相邻2项的和
代码示范:
#!/bin/python3
#-*- coding: UTF-8 -*-
lst = [1,4,9,16,2,5,10,15]
lstnew = [lst[i]+lst[i+1] for i in range(len(lst)-1)]
print(lstnew)
运行结果:
[5, 13, 25, 18, 7, 15, 25]
考点
- 严格按照工作过程和列表解析式的定义,套用至少一个for循环或多个for循环
- for循环必须是连续在一起的,for循环不能分开
正确示范代码:
#!/bin/python3
#-*- coding: UTF-8 -*-
lst = [print("{}*{}={:<3}{}".format(j,i,j*i,"\n" if i==j else ""),end="") for i in range(1,10) for j in range(1,i+1)]
print(lst)
运行结果:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
切忌for j循环写入format中,如果将j循环写入format中时,违反了代码语法:[expr for iter_val in iterable for iter_val in iterable],若违反代码语法肯定报错,根据工作过程知道,首先进行循环i,迭代到1时,返回给expr表达式print(),print的返回值构成新的列表。
另外:最后一个for循环表示要出现的次数,下面错误代码中示范的案例表明只会出现10个相乘的数,因此和题意完全不符,
错误示范代码:
#!/bin/python3
#-*- coding: UTF-8 -*-
lst = [print("{}*{}={:<3}{}".format(j,i,j*i,"\n" if i==j else ""),end="") for i in range(1,10) for j in range(1,i+1)]
print(lst)
运行结果:
SyntaxError: Generator expression must be parenthesized if not sole argument
SyntaxError:如果不是唯一参数,则必须将生成器表达式加括号
要求ID格式是以点号分割,左边是4为从1开始的整数,右边是10位随机小写英文字母,请依次生成前100个ID的列表
#!/bin/python3
#-*- coding: UTF-8 -*-
import random
string = "abcdefghigklmnopqrstuvwsyz"
lst = ["{:04}.{}".format(i,"".join(string[random.randint(0,25)] for j in range(10))) for i in range(1,4)]
print(lst)
运行结果:
['0001.mgdpsgtcqa', '0002.kduzdfncds', '0003.itohqzghzk']
#嵌套正确代码
string = "abcdefghigklmnopqrstuvwsyz"
lst = ["{:04}.{}".format(i,"".join(string[random.randint(0,25)] for j in range(10))) for i in range(1,4)]
print(lst)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#嵌套非正确代码
lst = ["{}*{}".format(i,j for j in range(1,i+1)) for i in range(1,10)]
print(lst)
#嵌套说明问题
当生成i*j个的expr表达式时,嵌套for时,两个for时兄弟并联关系
当生成i个expr表达式的值时,在expr表达式内可以可以嵌套for循环,但是expr表达式内的for循环和语法糖中的for循环毫无关系
lst={‘Tom’:15,’Jerry’:18,’Peter’:13}
#!/bin/python3
#-*- coding: UTF-8 -*-
dic = {
'Tom':15,'Jerry':18,'Peter':13}
lst = [(x,y) for x,y in dic.items()]
print(lst)
运行结果:
[('Jerry', 18), ('Tom', 15), ('Peter', 13)]
lst = [‘TOM’,’Peter’,10,’Jerry’]
#!/bin/python3
#-*- coding: UTF-8 -*-
lst = ['TOM','Peter',10,'Jerry']
lst0 = [x.lower() if isinstance(x,str) else x for x in lst]
lst1 = list(map(lambda x:x.lower() if isinstance(x,str) else x,lst))
print(lst0)
print(lst1)
运行结果:
['tom', 'peter', 10, 'jerry']
['tom', 'peter', 10, 'jerry']
lst = [‘TOM’,’Peter’,10,’Jerry’]
#!/bin/python3
#-*- coding: UTF-8 -*-
lst = ['TOM','Peter',10,'Jerry']
lst0 = [x.lower() for x in lst if isinstance(x,str)]
lst1 = list(map(lambda x:x.lower(),filter(lambda x: isinstance(x,str),lst)))
print(lst0)
print(lst1)
运行结果:
['tom', 'peter', 'jerry']
['tom', 'peter', 'jerry']
A function which returns a generator iterator. It looks like a normal function except that it contains yield expressions for producing a series of values usable in a for-loop or that can be retrieved one at a time with the next() function.
返回生成器迭代器的函数。 它看起来像一个普通的函数,只是它包含yield表达式,用于生成一系列可用于for-loop的值,或者可以使用next()函数一次检索一个值。
generator iterator
An object created by a generator function,Each yield temporarily suspends processing, remembering the location execution state (including local variables and pending try-statements). When the generator iterator resumes, it picks-up where it left-off (in contrast to functions which start fresh on every invocation).
生成器迭代器是通过生成器生成的一个对象,每次遇到yield时会暂停生产值并记住位置,当再次遇到迭代时它会在从暂停的位置重新开始,
其实生成器就是迭代器中的一种表现形式但是不同的对象,而且都是可迭代对象,后面有实验证明[在迭代器判断中],
生成器的构成是通过两种方式:
- 使用类似列表的方式生成
具体信息如下:
1.语法格式(返回值 for 元素 in 可迭代对象 if条件)
2.列表解析式的中括号换成小括号即可
3.返回一个生成器
- 使用包含yield的函数来生成
通常情况下对应简单的列表等采用列表生成器,若遇到复杂的计算值采用yield函数构成。
执行过程:
在执行过程中,遇到yield关键字就会终端执行,下次继续从中断位置开始执行。
特性:
1.与列表解析式截然不同,列表解析式是立即返回一个完整的列表,生成器表达式是按需计算,惰性求值,需要是才进行求值;
2.遇到yield记录当前位置,下次从记录位置继续执行
3.从前到后走完一遍后,不能回头
代码及特性示范1:
#!/bin/python3
#-*- coding: UTF-8 -*-
g = ("{:04}".format(i) for i in range(1,6))
print(next(g))
for x in g:
print(x)
print('~~~~~~~~~~~~')
for x in g:
print(x)
运行结果:
0001
0002
0003
0004
0005
~~~~~~~~~~~~
代码示范2:
expr表达式返回值构成列表或生成器,若无返回值时反回NoneTpye
#!/bin/python3
#-*- coding: UTF-8 -*-
#val的值是什么?
#val=first+second语句之后能否再next()?
g = (print('{}'.format(i+1)) for i in range(2))
first = next(g)
second = next(g)
val = first + second
print(val)
print(next(g))
运行结果:
1
2
Traceback (most recent call last):
File "./gen.py", line 9, in
val = first + second
TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'
代码示范3:
#!/bin/python3
#-*- coding: UTF-8 -*-
#val的值是什么?
#val=first+second语句之后能否再next()?
g = (x for x in range(10) if x % 2)
#取奇数1,3,5,7,9 first=1 second=3 val=4 下一个为5
first = next(g)
second = next(g)
val = first + second
print(val)
print(next(g))
运行结果:
4
5
g = (x for x in range(10))
def func():
yield
生成器表达式延迟计算,列表解析式立即计算
#!/bin/python3
#-*- coding: UTF-8 -*-
import datetime
import sys
start = datetime.datetime.now()
lst = [ x for x in range(10000000) ]
delta = (datetime.datetime.now() - start).total_seconds()
print("列表解析式耗时:{}".format(delta))
print("列表解析式耗内存:{}".format(sys.getsizeof(lst)))
start0 = datetime.datetime.now()
lst = ( x for x in range(10000000) )
delta0 = (datetime.datetime.now() - start0).total_seconds()
print("列表生成式耗时:{}".format(delta0))
print("列表生成式耗内存:{}".format(sys.getsizeof(lst)))
start1 = datetime.datetime.now()
def test_gen(start,end):
for x in range(start,end):
yield x
lst =test_gen(0,10000000)
delta1 = (datetime.datetime.now() - start1).total_seconds()
print("列表生成器函数耗时:{}".format(delta1))
print("列表生成器函数耗内存:{}".format(sys.getsizeof(lst)))
运行结果:
列表解析式耗时:0.328316
列表解析式耗内存:81528056
列表生成式耗时:0.104485
列表生成式耗内存:88
列表生成器函数耗时:1.2e-05
列表生成器函数耗内存:88
可直接用于for循环的对象统称为可迭代对象(Iterable)
判断是否是可迭代对象,用函数isinstance()
#!/bin/python3
#-*- coding: UTF-8 -*-
from collections import Iterable
print(isinstance("abc",Iterable))
print(isinstance("[]",Iterable))
print(isinstance("{}",Iterable))
print(isinstance("()",Iterable))
print(isinstance("(x,for x in range(2))",Iterable))
运行结果:
True
True
True
True
True
An object representing a stream of data. Repeated calls to the iterator’s next() method (or passing it to the built-in function next()) return successive items in the stream. When no more data are available a StopIteration exception is raised instead. At this point, the iterator object is exhausted and any further calls to its next() method just raise StopIteration again.
表示数据流的对象。 重复调用迭代器的next ()方法(会返回流中的连续项。直到没有数据可以返回时抛出StopIteration异常错误。可以把这个数据流看做一个有序序列,但我们无法提前知道这个序列的长度。同时,Iterator的计算是惰性的,只有通过next()函数时才会计算并返回下一个数据。
通过定义及判断可知,生成器也是迭代器,但是不是同一个对象,通过type返回值不一样
#!/bin/python3
#-*- coding: UTF-8 -*-
from collections import Iterator
print(isinstance("abc",Iterator))
print(isinstance("()",Iterator))
print(isinstance((x for x in range(2)),Iterator))