内容简介:你知道以下语法之间的区别吗?本文将向您介绍这里的区别。首先,对列表进行简短回顾(在其他编程语言中通常称为“数组”):
你知道以下语法之间的区别吗?
[x for x in range(5)] (x for x in range(5)) tuple(range(5))
本文将向您介绍这里的区别。
关于列表的5个事实
首先,对列表进行简短回顾(在其他编程语言中通常称为“数组”):
列表是一种可以表示为元素集合的数据。一个简单的列表如下所示:[0, 1, 2, 3, 4, 5]
列表将所有可能类型的数据和数据组合作为其元素:
>>> a = 12 >>> b = "this is text" >>> my_list = [0, b, ['element', 'another element'], (1, 2, 3), a] >>> print(my_list) [0, 'this is text', ['element', 'another element'], (1, 2, 3), 12]
列表可以编入索引。您可以使用以下语法访问任何单个元素或元素组:
>>> a = ['red', 'green', 'blue'] >>> print(a[0]) red
与字符串不同,列表在 Python 中是可变的。这意味着您可以替换,添加或删除元素。
您可以使用for循环和range()函数创建列表。
>>> my_list = [] >>> for x in range(10): ... my_list.append(x * 2) ... >>> print(my_list) [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
好的 - 那么列表推导是什么?
通常被视为Python中函数式编程的一部分,列表推导允许您使用包含较少代码的for循环创建列表。
使用列表推导来查看前一个示例的实现:
>>> comp_list = [x * 2 for x in range(10)] >>> print(comp_list) [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
上面的示例过于简单,可以让您了解语法。使用更简单的list(range(0, 19, 2))功能可以实现相同的结果。
您还可以在推导的第一部分中使用更复杂的修改器,或添加将过滤列表的条件。像这样的东西:
>>> comp_list = [x ** 2 for x in range(7) if x % 2 == 0] >>> print(comp_list) [4, 16, 36]
另一个可用选项是使用列表推导来组合多个列表并创建列表列表。乍一看,语法似乎很复杂。将列表视为外部序列和内部序列可能会有所帮助。
当您想要通过组合两个现有列表来创建列表列表时,是时候展示列表推导的强大功能了:
>>> nums = [1, 2, 3, 4, 5] >>> letters = ['A', 'B', 'C', 'D', 'E'] >>> nums_letters = [[n, l] for n in nums for l in letters] #the comprehensions list combines two simple lists in a complex list of lists. >>> print(nums_letters) >>> print(nums_letters) [[1, 'A'], [1, 'B'], [1, 'C'], [1, 'D'], [1, 'E'], [2, 'A'], [2, 'B'], [2, 'C'], [2, 'D'], [2, 'E'], [3, 'A'], [3, 'B'], [3, 'C'], [3, 'D'], [3, 'E'], [4, 'A'], [4, 'B'], [4, 'C'], [4, 'D'], [4, 'E'], [5, 'A'], [5, 'B'], [5, 'C'], [5, 'D'], [5, 'E']] >>>
让我们用文本尝试它,或者说字符串对象是正确的。
>>> iter_string = "some text" >>> comp_list = [x for x in iter_string if x !=" "] >>> print(comp_list) ['s', 'o', 'm', 'e', 't', 'e', 'x', 't']
推导不仅限于列表。您也可以创建dicts并设置推导。
>>> dict_comp = {x:chr(65+x) for x in range(1, 11)} >>> type(dict_comp) <class 'dict'> >>> print(dict_comp) {1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F', 6: 'G', 7: 'H', 8: 'I', 9: 'J', 10: 'K'} >>> set_comp = {x ** 3 for x in range(10) if x % 2 == 0} >>> type(set_comp) <class 'set'> >>> print(set_comp) {0, 8, 64, 512, 216}
Iterable和Iterator之间的区别
如果你了解了迭代和迭代器,那么理解生成器的概念会更容易。
Iterable是数据的“序列”,您可以使用循环迭代。可迭代的最简单可见示例可以是整数列表 - [1, 2, 3, 4, 5, 6, 7]。可以迭代其他类型的数据,如字符串,dicts,元组,集合等。
基本上,任何具有iter()方法的对象都可以用作可迭代的。您可以使用hasattr()解释器中的函数进行检查。
>>> hasattr(str, '__iter__') True >>> hasattr(bool, '__iter__') False
迭代一系列数据时,就会实现迭代器协议。例如,当您使用for循环时,后台发生以下情况:
iter()在对象上调用第一个方法将其转换为迭代器对象。
在迭代器对象上调用该方法以获取序列的下一个元素。 next()
如果StopIteration没有要调用的元素,则会引发异常。
>>> simple_list = [1, 2, 3] >>> my_iterator = iter(simple_list) >>> print(my_iterator) <list_iterator object at 0x7f66b6288630> >>> next(my_iterator) 1 >>> next(my_iterator) 2 >>> next(my_iterator) 3 >>> next(my_iterator) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
生成器表达式(generator expression)
在Python中,生成器提供了一种实现迭代器协议的便捷方式。Generator是一个使用带有yield语句的函数创建的迭代。
生成器的主要特征是按需评估元素。当您使用return语句调用普通函数时,只要遇到return语句,函数就会终止。
在带有yield语句的函数中,函数的状态从上次调用中“保存”,并且可以在下次调用生成函数时被拾取
>>> def my_gen(): ... for x in range(5): ... yield x
生成器表达式允许在没有yield关键字的情况下即时创建生成器。但是它们不能分享用yield函数创建的生成器的全部功能。
语法和概念类似于列表推导的语法和概念:
>>> gen_exp = (x ** 2 for x in range(10) if x % 2 == 0) >>> for x in gen_exp: ... print(x) 0 4 16 36 64
在语法方面,唯一的区别是你使用括号而不是方括号。
列表推导和生成器表达式返回的数据类型不同。
>>> list_comp = [x ** 2 for x in range(10) if x % 2 == 0] >>> gen_exp = (x ** 2 for x in range(10) if x % 2 == 0) >>> print(list_comp) [0, 4, 16, 36, 64] >>> print(gen_exp) <generator object <genexpr> at 0x7f600131c410>
生成器在列表中的主要优点是它占用的内存要少得多。我们可以使用sys.getsizeof()方法检查两种类型占用的内存量。
注意:在Python 2中,使用range()函数实际上无法反映大小方面的优势,因为它仍然将整个元素列表保存在内存中。但是,在Python 3中,这个例子是可行的,因为它range()返回一个范围对象。
>>> from sys import getsizeof >>> my_comp = [x * 5 for x in range(1000)] >>> my_gen = (x * 5 for x in range(1000)) >>> getsizeof(my_comp) 9024 >>> getsizeof(my_gen) 88
生成器一次生成一个项目 - 因此它比列表更有内存效率。
例如,当您想迭代列表时,Python会为整个列表保留内存。生成器不会将整个序列保留在内存中,并且只会根据需要“生成”序列的下一个元素。
最后的想法
可能会吓到或劝阻新手 程序员 的第一件事就是教育材料的规模。这里的诀窍是将每个概念视为语言提供的选项,您不应该同时学习所有语言概念和模块。
总有不同的方法来解决同一个任务。把它作为完成工作的另一个工具。
查看更多文章:www.apexyun.com
公众号:银河系1号
联系邮箱:public@space-explore.com
(未经同意,请勿转载)
以上所述就是小编给大家介绍的《Python列表推导(list comprehension)VS 生成器表达式(generator expression)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
哥德尔、艾舍尔、巴赫
[美] 侯世达 / 严勇、刘皓明、莫大伟 / 商务印书馆 / 1997-5 / 88.00元
集异璧-GEB,是数学家哥德尔、版画家艾舍尔、音乐家巴赫三个名字的前缀。《哥德尔、艾舍尔、巴赫书:集异璧之大成》是在英语世界中有极高评价的科普著作,曾获得普利策文学奖。它通过对哥德尔的数理逻辑,艾舍尔的版画和巴赫的音乐三者的综合阐述,引人入胜地介绍了数理逻辑学、可计算理论、人工智能学、语言学、遗传学、音乐、绘画的理论等方面,构思精巧、含义深刻、视野广阔、富于哲学韵味。 中译本前后费时十余年,......一起来看看 《哥德尔、艾舍尔、巴赫》 这本书的介绍吧!