この記事では、python に関する関連知識を提供します。主に、コンテナー、反復可能オブジェクト、イテレーター、およびジェネレーターに関する関連問題を紹介します。一緒に見てみましょう。皆さんのご協力を願っています。
推奨学習: Python ビデオ チュートリアル
Python を初めて学習し始めたとき、私たちが話している偉人たちの話をよく聞きましたか?コンテナー、反復可能なオブジェクト、イテレーター、ジェネレーター、リスト/セット/辞書の内包表記、その他多くの概念について実際、これは大手が B のふりをするために専門用語を使っているだけだからではなく、これらのことは理解する必要があります。特に Python のデータ構造に関しては、文字列やリストなどの基本を知っているだけでは十分ではありません。
今日は、Python の基礎を次のレベルに引き上げるために、Python のコンテナ、反復可能オブジェクト、イテレータ、ジェネレータの理解しにくい概念について説明します。
Python では、コンテナとは複数の要素をまとめたデータ構造であり、コンテナ内の要素は 1 つずつ繰り返し取得できます。端的に言えば、その機能はその名の通り、物(データ)を保存するために使用されます。
コンテナは実際には存在しません。データ型ではなく、人が作った概念です。学習を容易にするために作成された単なる概念単語です。メンバーシップ演算子 (in または not in ) とともに使用できます。 ) オブジェクトがコンテナ内にあるかどうかを判断します。
もちろん、これは私が作ったものではありません。私にはそんな能力はありません。政府が作ったものです。心配する必要はありません。変な用語を教えています。あなたが言うと、他の人も聞くでしょう、わかりません...Python ではそう呼ばれます。 一般的なコンテナ タイプには、リスト (list)、タプル (tuple)、文字列 (str)、辞書 (dict)、およびセット (set) があります。
コンテナ内のデータは反復的に取得できるため、反復可能オブジェクトという新しい概念を学ぶ必要があります。
Python では、反復可能オブジェクトは特定のデータ型を参照するのではなく、要素を格納するコンテナ オブジェクトを参照します。
言い換えると、コンテナにデータが格納されていない場合、そのコンテナは反復可能オブジェクトではありません。すべてのコンテナが反復可能オブジェクトであるわけではありません。コンテナには反復可能オブジェクトが含まれますが、これに限定されません。
2 つの点に注意してください:
1.很多容器都是可迭代对象(容器包含了可迭代对象)。 2.一个可迭代对象是不能独立的进行迭代的,迭代是通过for来完成的,凡是可迭代对象都可以直接使用for循环进行访问。
for ループについてはよく知っているはずです。 for ループがどのように実装されているか疑問に思ったことはありますか?たとえば、この for ループの例では、なぜリスト内のすべての要素を出力できるのでしょうか?内部的にはどのように実装されていますか?
実際、for ループは 2 つのことを行います:
1.使用 __iter__() 返回1个迭代器,迭代器在下面会讲,这里先知道有这么个东西。 2.使用 __next__() 获取迭代器中的每一个元素。
したがって、それぞれを出力するのに for ループは必要ありません。 list 内の要素、
l = [1,2,3,4]# for i in l:# print(i)ite =l.__iter__() #接收一下ietr()干了什么print(ite) #打印print(ite.__next__()) #for循环干第2件事情的时候做的第1步print(ite.__next__()) #for循环干第2件事情的时候做的第2步print(ite.__next__()) #for循环干第2件事情的时候做的第3步print(ite.__next__()) #for循环干第2件事情的时候做的第4步
出力結果:
これを出力するコード行を削除すると、実行効果が次のようになります。 for ループの出力リストと同じである 各要素は同じです for ループでは範囲が 4 回に制限されています。実際には、__iter__() が 1 回、__next__() が 4 回実行されます。 for ループで繰り返しオブジェクトにアクセスすることでこれを実現します。
さらに、for ループが本質的に行う 2 つのことは不可欠です。つまり、__iter__() が最初に反復子を返さない場合、__next()__ は要素を正確に取得できません。前述の 2 つのポイントのうちの 2 番目のポイント: 反復可能なオブジェクトは独立して反復することはできません。
同じ原理と本質を持つ 2 つの組み込み関数があります。一般的に言えば、組み込み関数を使用する方が便利です。少なくとも、それほど多くのアンダースコアを記述する必要はありません:
内置函数 iter() 的本质是 __inter__() ,也是返回一个迭代器。 内置函数 next() 的本质是 __next__(),也是有了迭代器之后获取元素。
結果はまったく同じであることがわかります。イテレータについて説明したので、イテレータとは何かを見てみましょう。
おそらく、上記の for ループの例を通してそれを見ることができます。
只要是实现了__iter__()和__next__()的对象,就是迭代器,迭代器是一个可迭代对象。 总之,迭代器是有__iter__()生成,可以通过__next__()进行调用。
この場合、range( の基礎を学んでいたときに話しました。 Python ) は反復可能なオブジェクトであり、 __iter__() を通じて反復子を生成することもできます。
シーケンスについては、特集記事 [代入文] で触れましたが、ここでもう一度説明します。 ## シーケンスもリスト、タプル、文字列などを含む抽象的な概念です それ自体は存在せず、学習を容易にするために作られた概念語でもあります。
可迭代对象包含序列,既然序列包含了列表、元组和字符串,前面我们的例子中也涉及到 了,所以说序列可以被iter()和next()使用。
序列可以分为有限序列和无限序列。有限序列就是有范围的,比如说range(10)就已经限定了范围,相反的,无限序列也就是没有限定范围的序列。
我们来生成一个无限序列,这里需要用到1个新模块itertools,itertools用于高效循环的迭代函数集合,它下面有一个方法count(),可生成迭代器且无范围,可以理解为无限迭代器。
通过这个例子我们可以看出来,只要执行一次,next()就会获取一次迭代器里面的内容并逐次获取,我这里只写了4个next(),你多写几次就会多输出几次。
像next()这种什么时候需要就什么时候调用的机制叫做懒加载机制,也叫懒汉式加载;
相反地就有饿汉式加载。比如for循环这种的,只要一执行就会把可迭代器里面的所有对象都获取。
列表推导式跟生成器有关,在讲生成器之前,需要先知道什么是列表推导式,列表推导式就是生成列表的一种方法,语法是这样的:
l = [i for i in 可迭代对象]
i表示要放进列表里的对象,for循环是一个式子。
比如我们用列表推导式来生成一个列表试试:
l = [i for i in range(5)]print(l)
运行结果:
[0, 1, 2, 3, 4]
运用列表推导式可以很方便地生成我们想要的列表。
同时它也有很多灵活的用法,比如在后面加上条件判断
l = [i for i in range(5) if 4<p>运行结果:</p><pre class="brush:php;toolbar:false">[0, 1, 2, 3, 4]
if后面的条件判断为真,则可以正常生成列表,如果为假,则列表推导式是无效的,此时的l将是一个空列表。
还有其他灵活的用法,比如操作前面的i,比如让i的数值全都翻2倍:
我们把迭代对象换一下,换成字符串,也同样可以输出,只是*在字符串里面表示重复操作符,所以效果变成了这样:
不仅如此,前面的i*2我们还可以用函数来进行操作,比如:
总而言之,列表推导式就是用来快速和自定义生成列表的一种方法,很灵活。
那么有人可能会举一反三了,列表推导式都是用 [] 来进行操作的,那如果用()来操作行吗?它会不会生成一个元组?我们来看看:
[] 换成()之后,返回的是一个生成器generrator ,那么下面我们再来讲讲生成器:
生成器是真实存在于Python中的对象,与容器这种概念词是不同的,它是可以直接通过next()进行调用的。
第一种创建方法跟列表推导式是差不多的,就是 [] 换成了():
l = (i for i in 可迭代对象)
比如我们来生成一个生成器,看看能不能用next()直接调用:
l = (i for i in "abcd")print(next(l))
运行结果:
a
可以看出,生成器是可以直接调用的。那么既然生成器可以被next()调用,那么生成器就是一个特殊的迭代器,是一个可迭代对象。
除了用上面那种方法创建生成器,还可以用yield来创建,方法如下:
yield 关键字
比如说我们用一个函数中包含yield来创建生成器:
def fun(): a = 10 while 1: a += 1 yield a b = fun()print(b)
运行结果:
<generator></generator>
结果就是生成了一个生成器,而且此时的函数fun()就已经不再是一个函数了,它是一个生成器,只要函数中出现了yield,函数就变成了生成器。
为什么while循环没有一直执行?先不着急,我们输出看看:
def fun(): a = 10 while 1: a += 1 yield a b = fun()print(next(b))print(next(b))print(next(b))
运行结果:
111213
我调用了三次,所以它就运行了三次,while循环虽然存在,但是却不起作用,是因为前面我们提过的懒汉式加载。
什么时候需要了,什么时候用next()调用,就是懒汉式加载,不像饿汉式加载那样,提前生成了所有对象,如果这里换成for循环来完成,比如:
def fun(): a = 10 while 1: a += 1 print(a)b = fun()
运行之后程序将会进入死循环,一直给a自加1,你可以试试看效果,这就是饿汉式加载提前生成了迭代器并调用了全部迭代器对象,饿汉式加载占用资源的放大镜。
今天讲的内容可能听起来比较枯燥,这也是没得办法的,有些东西第一次听可能有点”难以下咽“,见得多了之后就习惯了,你得强迫自己去试着接受和理解这些抽象的东西。
最后用一张图来总结一下它们的关系:
推荐学习:python教程
以上がコンテナー、反復可能オブジェクト、イテレーター、ジェネレーターの Python の詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。