Python'un Jeneratörleri ve Yineleyiciler Arasındaki Fark


538

Yineleyiciler ve jeneratörler arasındaki fark nedir? Her vakayı ne zaman kullanacağınıza dair bazı örnekler yardımcı olacaktır.

Yanıtlar:


543

iteratorolan sınıf olan herhangi bir nesne: daha genel bir kavramdır next(yöntem __next__Python 3) ve __iter__yapar yöntem return self.

Her jeneratör bir yineleyicidir, ancak tersi değildir. Bir veya daha fazla yieldifadeye ( yieldPython 2.5 ve önceki sürümlerinde ifadeler) sahip bir işlev çağırarak oluşturucu oluşturulur ve önceki paragrafın bir iterator.

Biraz karmaşık durum koruma davranışına sahip bir sınıfa ihtiyacınız olduğunda veya next( __iter__ve __init__) dışında başka yöntemler göstermek istediğinizde, bir jeneratör yerine özel bir yineleyici kullanmak isteyebilirsiniz . Çoğu zaman, bir jeneratör (bazen, yeterince basit ihtiyaçlar için, bir jeneratör ifadesi ) yeterlidir ve kodlanması daha kolaydır, çünkü durum bakımı (makul sınırlar dahilinde) temel olarak çerçevenin askıya alınması ve devam ettirilmesi tarafından "sizin için yapılır".

Örneğin, aşağıdaki gibi bir jeneratör:

def squares(start, stop):
    for i in range(start, stop):
        yield i * i

generator = squares(a, b)

veya eşdeğer jeneratör ifadesi (genexp)

generator = (i*i for i in range(a, b))

özel bir yineleyici olarak oluşturmak için daha fazla kod gerekir:

class Squares(object):
    def __init__(self, start, stop):
       self.start = start
       self.stop = stop
    def __iter__(self): return self
    def next(self): # __next__ in Python 3
       if self.start >= self.stop:
           raise StopIteration
       current = self.start * self.start
       self.start += 1
       return current

iterator = Squares(a, b)

Ancak, elbette, sınıfla Squareskolayca ekstra yöntemler sunabilirsiniz, yani

    def current(self):
       return self.start

uygulamanızda bu tür ekstra işlevlere gerçekten ihtiyacınız varsa.


oluşturduktan sonra yineleyiciyi nasıl kullanırım?
Vincenzooo

@Vincenzooo, onunla ne yapmak istediğinize bağlı. Ya for ... in ...:iter.next()
a'nın

@Caleth Tam sözdizimini soruyordum, çünkü for..insözdizimini kullanmaya çalışırken hata alıyordum . Belki bir şey eksikti, ama bir süre önce, çözdüğümü hatırlamıyorum. Teşekkür ederim!
Vincenzooo

136

Yineleyiciler ve jeneratörler arasındaki fark nedir? Her vakayı ne zaman kullanacağınıza dair bazı örnekler yardımcı olacaktır.

Özetle: Yineleyiciler, __iter__ve __next__( nextPython 2'de) yöntemine sahip nesnelerdir . Jeneratörler, Yineleyiciler örnekleri oluşturmak için kolay ve yerleşik bir yol sağlar.

İçinde verim olan bir işlev, çağrıldığında bir jeneratör nesnesinin bir örneğini döndüren bir işlevdir:

def a_function():
    "when called, returns generator object"
    yield

Bir jeneratör ifadesi ayrıca bir jeneratör döndürür:

a_generator = (i for i in range(0))

Daha ayrıntılı bir açıklama ve örnekler için okumaya devam edin.

Bir Jeneratör olan bir Iterator

Özellikle, jeneratör yineleyicinin bir alt türüdür.

>>> import collections, types
>>> issubclass(types.GeneratorType, collections.Iterator)
True

Jeneratörü birkaç yolla oluşturabiliriz. Bunu yapmanın çok yaygın ve basit bir yolu bir işlevdir.

Özellikle, içinde verim olan bir işlev, çağrıldığında bir jeneratör döndüren bir işlevdir:

>>> def a_function():
        "just a function definition with yield in it"
        yield
>>> type(a_function)
<class 'function'>
>>> a_generator = a_function()  # when called
>>> type(a_generator)           # returns a generator
<class 'generator'>

Ve yine bir jeneratör bir Yineleyici:

>>> isinstance(a_generator, collections.Iterator)
True

Bir Yineleyici olan bir iterable

Bir Yineleyici Yinelenebilir,

>>> issubclass(collections.Iterator, collections.Iterable)
True

hangi gerektirir __iter__bir Yineleyici döndüren bir yöntem :

>>> collections.Iterable()
Traceback (most recent call last):
  File "<pyshell#79>", line 1, in <module>
    collections.Iterable()
TypeError: Can't instantiate abstract class Iterable with abstract methods __iter__

Tekrarlanabilir bazı örnekler yerleşik tuples, listeler, sözlükler, kümeler, dondurulmuş kümeler, dizeler, bayt dizeleri, bayt dizileri, aralıklar ve bellek görünümleridir:

>>> all(isinstance(element, collections.Iterable) for element in (
        (), [], {}, set(), frozenset(), '', b'', bytearray(), range(0), memoryview(b'')))
True

Yineleyiciler gerektirir bir nextveya __next__yöntem

Python 2'de:

>>> collections.Iterator()
Traceback (most recent call last):
  File "<pyshell#80>", line 1, in <module>
    collections.Iterator()
TypeError: Can't instantiate abstract class Iterator with abstract methods next

Ve Python 3'te:

>>> collections.Iterator()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Iterator with abstract methods __next__

Yineleyicileri iterişlevli yerleşik nesnelerden (veya özel nesnelerden) alabiliriz :

>>> all(isinstance(iter(element), collections.Iterator) for element in (
        (), [], {}, set(), frozenset(), '', b'', bytearray(), range(0), memoryview(b'')))
True

__iter__Eğer bir dongu ile bir nesneyi kullanma girişiminde yöntemi olarak adlandırılır. Sonra__next__ döngü için her öğeyi almak için yineleyici nesnesinde yöntem çağrılır. Yineleyici, StopIterationtükendiğinde yükselir ve bu noktada tekrar kullanılamaz.

Belgelerden

Yerleşik Türler belgelerinin Yineleyici Türleri bölümünün Jeneratör Türleri bölümünden :

Python'un jeneratörleri, yineleyici protokolünü uygulamak için uygun bir yol sağlar. Bir kapsayıcı nesnesinin __iter__()yöntemi bir oluşturucu olarak uygulanırsa, __iter__()ve next()[ __next__()Python 3'te] yöntemlerini sağlayan bir yineleyici nesnesini (teknik olarak bir oluşturucu nesnesi) otomatik olarak döndürür . Jeneratörler hakkında daha fazla bilgi verim ifadesi belgelerinde bulunabilir.

(Vurgu eklendi.)

Bundan dolayı Jeneratörlerin (uygun) bir Yineleyici olduğunu öğreniyoruz.

Örnek Yineleyici Nesneleri

Kendi nesnenizi oluşturarak veya genişleterek Iterator protokolünü uygulayan nesne oluşturabilirsiniz.

class Yes(collections.Iterator):

    def __init__(self, stop):
        self.x = 0
        self.stop = stop

    def __iter__(self):
        return self

    def next(self):
        if self.x < self.stop:
            self.x += 1
            return 'yes'
        else:
            # Iterators must raise when done, else considered broken
            raise StopIteration

    __next__ = next # Python 3 compatibility

Ancak bunu yapmak için bir Jeneratör kullanmak daha kolaydır:

def yes(stop):
    for _ in range(stop):
        yield 'yes'

Ya da belki daha basit bir Jeneratör İfadesi (liste kavrayışlarına benzer şekilde çalışır):

yes_expr = ('yes' for _ in range(stop))

Hepsi aynı şekilde kullanılabilir:

>>> stop = 4             
>>> for i, y1, y2, y3 in zip(range(stop), Yes(stop), yes(stop), 
                             ('yes' for _ in range(stop))):
...     print('{0}: {1} == {2} == {3}'.format(i, y1, y2, y3))
...     
0: yes == yes == yes
1: yes == yes == yes
2: yes == yes == yes
3: yes == yes == yes

Sonuç

Tekrarlanabilir bir nesne olarak bir Python nesnesini genişletmeniz gerektiğinde Iterator protokolünü doğrudan kullanabilirsiniz.

Bununla birlikte, vakaların büyük çoğunluğunda, kullanmak için en uygunudur yield bir Jeneratör Yineleyicisi döndüren veya Jeneratör İfadelerini dikkate alan bir işlevi tanımlamak yöntemdir.

Son olarak, jeneratörlerin koroutin olarak daha fazla işlevsellik sağladığını unutmayın. Ben birlikte Jeneratörler açıklamak yieldverim "ne yok‘’do Keyword?" Cevabım üzerine derinlemesine, açıklamada.


41

yineleyiciler:

Yineleyici, next() sıralamanın bir sonraki değerini almak yöntem .

Jeneratörler:

Jeneratör, bir dizi değer üreten veya üreten bir işlevdir. yield yöntem .

Jeneratör işlevi tarafından döndürülen her next()yöntem çağrısı ( faşağıdaki örnekte olduğu gibi ex için ) ( foo()aşağıdaki örnekte ex: işlevi için ), sırayla bir sonraki değeri üretir.

Bir jeneratör işlevi çağrıldığında, işlevin yürütülmesine bile başlamadan bir jeneratör nesnesi döndürür. Tüm next()yöntem, ilk kez olarak adlandırılır bu vermiştir değerini verir verim deyimi ulaşana kadar, fonksiyon yürütmeye başlar. Verim, yani son yürütmeyi hatırlar. Ve ikinci next()çağrı önceki değerden devam eder.

Aşağıdaki örnek, üretken nesnesindeki verim ve sonraki yönteme çağrı arasındaki etkileşimi gösterir.

>>> def foo():
...     print "begin"
...     for i in range(3):
...         print "before yield", i
...         yield i
...         print "after yield", i
...     print "end"
...
>>> f = foo()
>>> f.next()
begin
before yield 0            # Control is in for loop
0
>>> f.next()
after yield 0             
before yield 1            # Continue for loop
1
>>> f.next()
after yield 1
before yield 2
2
>>> f.next()
after yield 2
end
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>>

3
Sadece FYI verimi yöntem değil, anahtar kelime
Jay Parikh

25

Mevcut cevapların hiçbiri resmi literatürdeki karışıklığa özellikle değinmediği için bir cevap eklemek.

Jeneratör işlevleriyield yerinekullanılarak tanımlanan sıradan işlevlerdirreturn. Bir jeneratör işlevi çağrıldığında, birtür yineleyici olanbir jeneratör nesnesini döndürür- birnext()yöntemi vardır. Aradığınızdanext(), jeneratör işlevi tarafından verilen bir sonraki değer döndürülür.

Okuduğunuz Python kaynak belgesine bağlı olarak ya işlev ya da nesne "jeneratör" olarak adlandırılabilir. Python sözlüğü olurken, jeneratör fonksiyonlarını diyor Python wiki jeneratör nesneleri ima eder. Python öğretici oldukça ima etmek yöneten hem üç cümle uzayda kullanımlarını:

Jeneratörler, yineleyiciler oluşturmak için basit ve güçlü bir araçtır. Normal işlevler gibi yazılırlar ancak veri döndürmek istedikleri zaman getiri ifadesini kullanırlar. Next () işlevinin her çağrılışında jeneratör kaldığı yerden devam eder (tüm veri değerlerini ve en son hangi cümleyi çalıştırdığını hatırlar).

İlk iki cümle jeneratör fonksiyonuna sahip jeneratörleri, üçüncü cümle ise jeneratör nesnelerini tanımlar.

Tüm bu karışıklığa rağmen , açık ve son kelime için Python dil referansını araştırabilirsiniz:

Verim ifadesi yalnızca bir jeneratör işlevi tanımlanırken kullanılır ve yalnızca bir işlev tanımının gövdesinde kullanılabilir. Bir işlev tanımında bir verim ifadesi kullanmak, bu tanımın normal bir işlev yerine bir üreteç işlevi oluşturmasına neden olmak için yeterlidir.

Bir jeneratör işlevi çağrıldığında, jeneratör olarak bilinen bir yineleyici döndürür. Bu jeneratör daha sonra bir jeneratör fonksiyonunun yürütülmesini kontrol eder.

Yani, resmi ve kesin kullanımda, "jeneratör" niteliksiz jeneratör fonksiyonu değil, jeneratör nesnesi anlamına gelir.

Yukarıdaki referanslar Python 2 içindir, ancak Python 3 dil referansı aynı şeyi söyler. Ancak, Python 3 sözlüğü devletler bu

jeneratör ... Genellikle bir jeneratör işlevini belirtir, ancak bazı bağlamlarda bir jeneratör yineleyicisini ifade edebilir. Amaçlanan anlamın net olmadığı durumlarda, tam terimlerin kullanılması belirsizliği önler.


Jeneratör işlevleri ve jeneratör nesneleri arasında çok fazla karışıklık olduğunu düşünmüyorum, aynı nedenle sınıflar ve örnekleri arasında genellikle karışıklık yok. Her iki durumda da, diğerini almak için birini çağırırsınız ve geçici konuşmada (veya hızlı bir şekilde yazılı belgelerde), her ikisi için de sınıf adını veya "jeneratör" kelimesini kullanabilirsiniz. Sadece "jeneratör işlevi" ve "jeneratör nesnesi" hakkında, hangisinden bahsettiğinizin nadir olduğu durumlarda açık olmanız gerekir.
Blckknght

6
1. Karışıklık olmaması için teorik nedenlerden bağımsız olarak, bu sorunun diğer cevapları hakkındaki yorumlar, gerçek karışıklığın mevcut olduğunu belirterek, çözüm olmaksızın birbirini reddeder ve çelişir. 2. Gündelik kesinsizlik iyidir, ancak kesin ve güvenilir bir kaynak en azından SO'daki seçeneklerden biri olmalıdır. Mevcut projemde hem jeneratör fonksiyonlarını hem de objeleri yoğun olarak kullanıyorum ve tasarım ve kodlamada ayrım çok önemli. Şimdi hangi terminolojinin kullanılacağını bilmek güzel, bu yüzden daha sonra onlarca değişken ismini ve yorumu değiştirmek zorunda değilim.
Paul

2
Bir fonksiyon ve onun dönüş değeri arasında hiçbir ayrım yapılmayan bir matematik literatürü düşünün. Onları gayri resmi olarak karıştırmak bazen uygundur, ancak çeşitli hata riskini artırır. Gelişmiş modern matematik, ayrım konvansiyon, dil ve gösterimde resmileşmezse, önemli ölçüde ve gereksiz yere engellenirdi.
Paul

2
Jeneratörlerin etrafından geçen üst düzey işlevler veya jeneratör işlevleri garip gelebilir, ancak benim için geliyorlar. Apache Spark'da çalışıyorum ve çok fonksiyonel bir programlama stili uyguluyor. İşlevler, işleri halletmek için her türlü nesneyi yaratmalı, aktarmalı ve dağıtmalıdır. Ne tür bir "jeneratör" ile çalıştığımı takip etmediğim birkaç durum yaşadım. Değişken adları ve yorumlarındaki ipuçları, tutarlı ve doğru terminolojiyi kullanarak karışıklığı gidermeye yardımcı oldu. Bir Pythonist'in belirsizliği, diğerinin proje tasarımının merkezi olabilir!
Paul

1
@ Paul, bu cevabı yazdığınız için teşekkürler. Bu karışıklık önemlidir, çünkü bir jeneratör nesnesi ile bir jeneratör işlevi arasındaki fark, istenen davranışı elde etmek ile jeneratörleri aramak zorunda kalmak arasındaki farktır.
blujay

15

Herkesin örneklerle gerçekten güzel ve ayrıntılı bir cevabı var ve bunu gerçekten takdir ediyorum. Kavramsal olarak hala çok net olmayan insanlar için birkaç satır kısa cevap vermek istedim:

Kendi yineleyicinizi oluşturursanız, biraz dahil olur - bir sınıf oluşturmanız ve en azından yineleyiciyi ve sonraki yöntemleri uygulamanız gerekir. Ama ya bu güçlükten geçmek istemiyorsanız ve hızlı bir şekilde bir yineleyici oluşturmak istiyorsanız. Neyse ki, Python bir yineleyici tanımlamak için kısa bir yol sağlar. Yapmanız gereken tek şey, en az 1 verim çağrısı olan bir işlev tanımlamaktır ve şimdi bu işlevi çağırdığınızda, bir yineleyici gibi davranacak bir şey döndürür (sonraki yöntemi çağırabilir ve bir for döngüsünde kullanabilirsiniz). Bu şeyin Python'da Generator adlı bir adı var

Umarım bu biraz açıklığa kavuşur.


10

Önceki cevaplar bu eklemeyi kaçırdı: bir jeneratörün bir closeyöntemi var, ancak tipik yineleyiciler yok. closeYöntem tetikler StopIterationa yakalanmış olabilir jeneratörü istisna,finally o yineleyici fıkra, bazı temizlik çalıştırmak için bir şans için. Bu soyutlama onu basit yineleyicilerden çok daha büyük oranda kullanılabilir hale getirir. Bir jeneratör, altında ne olduğunu rahatsız etmek zorunda kalmadan bir dosyayı kapatabileceği gibi kapatabilir.

Bununla birlikte, ilk soruya kişisel cevabım şöyle olurdu: yinelenebilir __iter__sadece bir yöntem var, tipik yineleyiciler sadece bir __next__yöntem var , jeneratörler hem bir hem de bir __iter__ve __next__ekclose .

İkinci soru için, kişisel cevabım şöyle olurdu: halka açık bir arayüzde, daha esnek olduğu için jeneratörleri tercih etme eğilimindeyim: closeyöntem daha büyük bir bileşimyield from . Yerel olarak yineleyicileri kullanabilirim, ancak yalnızca düz ve basit bir yapı (yineleyiciler kolayca oluşturmazsa) ve dizinin özellikle sona ulaşmadan durdurulabileceğine inanmak için nedenler varsa. Yineleyicilere değişmez değerler dışında düşük düzeyli bir ilkel olarak bakma eğilimindeyim.

Kontrol akışıyla ilgili konularda, jeneratörler vaatler kadar önemli bir kavramdır: her ikisi de soyut ve oluşturulabilir.


Kompozisyon hakkında konuşurken kastettiğinizi göstermek için bir örnek verebilir misiniz? Ayrıca, " tipik yineleyiciler" den söz ederken aklınızdakileri açıklayabilir misiniz ?
bli

1
Başka bir cevap ( stackoverflow.com/a/28353158/1878788 ) "bir yineleyicinin yinelenebilir olduğunu" belirtir. Bir yinelemenin bir __iter__yöntemi olduğundan, yineleyici nasıl olabilir __next__? Yinelenebilir olmaları gerekiyorsa, onların da mutlaka olmasını beklerdim __iter__.
bli

1
@bli: AFAICS buradaki bu cevap standart PEP234'ü ifade eder , bu yüzden doğrudur, diğer cevap bazı uygulamalara atıfta bulunur, bu yüzden sorgulanabilir. Standart __iter__, yalnızca bir nextyöntem ( __next__Python3'te) gerektiren bir yineleyiciyi döndürmek için yalnızca bir yinelenebilir açık gerektirir . Lütfen standartları (ördek yazmak için) uygulamalarıyla (belirli bir Python yorumlayıcısının nasıl uyguladığı) karıştırmayın. Bu biraz jeneratör fonksiyonları (tanım) ve jeneratör nesneleri (uygulama) arasındaki karışıklığa benzer. ;)
Tino

7

Jeneratör İşlevi, Jeneratör Nesnesi, Jeneratör:

Bir Generator işlevi Python'daki normal bir işlev gibidir, ancak bir veya daha fazla yieldifade içerir . Jeneratör fonksiyonları mümkün olduğunca kolay Iterator nesneleri oluşturmak için harika bir araçtır . Yineleyici jeneratör işlevi nesne returend da adlandırılır Jeneratör nesne ya da jeneratör .

Bu örnekte bir Generator nesnesi döndüren bir Generator işlevi oluşturdum <generator object fib at 0x01342480>. Diğer yineleyiciler gibi, Generator nesneleri de bir fordöngüde veya next()jeneratörden sonraki değeri döndüren yerleşik işlevle kullanılabilir.

def fib(max):
    a, b = 0, 1
    for i in range(max):
        yield a
        a, b = b, a + b
print(fib(10))             #<generator object fib at 0x01342480>

for i in fib(10):
    print(i)               # 0 1 1 2 3 5 8 13 21 34


print(next(myfib))         #0
print(next(myfib))         #1
print(next(myfib))         #1
print(next(myfib))         #2

Yani bir üreteç işlevi, bir Yineleme nesnesi oluşturmanın en kolay yoludur.

Yineleyici :

Her jeneratör nesnesi bir yineleyicidir, ancak tam tersi değildir. Sınıfı uygular __iter__ve __next__yöntemi (yineleyici protokolü olarak da bilinir) özel bir yineleyici nesnesi oluşturulabilir .

Ancak, jeneratörler fonksiyonu oluşturacağına kullanımı çok daha kolaydır yineleyicinızı onların oluşturulmasını basitleştirmek için değil, özel bir Yineleyici size daha fazla özgürlük verir ve aşağıdaki örnekte gösterildiği gibi siz de ihtiyaçlarına göre başka yöntemler uygulayabilir.

class Fib:
    def __init__(self,max):
        self.current=0
        self.next=1
        self.max=max
        self.count=0

    def __iter__(self):
        return self

    def __next__(self):
        if self.count>self.max:
            raise StopIteration
        else:
            self.current,self.next=self.next,(self.current+self.next)
            self.count+=1
            return self.next-self.current

    def __str__(self):
        return "Generator object"

itobj=Fib(4)
print(itobj)               #Generator object

for i in Fib(4):  
    print(i)               #0 1 1 2

print(next(itobj))         #0
print(next(itobj))         #1
print(next(itobj))         #1

6

Yin Batchelder'dan yineleyiciler ve jeneratörler için şiddetle tavsiye edilen örnekler

Sayılara bir şey yapan jeneratörsüz bir yöntem

def evens(stream):
   them = []
   for n in stream:
      if n % 2 == 0:
         them.append(n)
   return them

bir jeneratör kullanarak

def evens(stream):
    for n in stream:
        if n % 2 == 0:
            yield n
  • Listeye veya returnifadeye ihtiyacımız yok
  • Büyük / sonsuz uzunluk akışı için verimli ... sadece yürür ve değeri verir

evensYöntemi (jeneratör) çağırmak her zamanki gibi

num = [...]
for n in evens(num):
   do_smth(n)
  • Jeneratör çift döngüyü kırmak için de kullanılır

yineleyici

Sayfalarla dolu bir kitap yinelenebilir , Yer işareti yineleyicidir

ve bu yer iminin taşınmak dışında bir ilgisi yok next

litr = iter([1,2,3])
next(litr) ## 1
next(litr) ## 2
next(litr) ## 3
next(litr) ## StopIteration  (Exception) as we got end of the iterator

Jeneratörü kullanmak için ... bir fonksiyona ihtiyacımız var

Yineleyici kullanmak için ... İhtiyacımız nextveiter

Söylendiği gibi:

Bir Generator işlevi bir iterator nesnesini döndürür

Yineleyicinin tüm yararı:

Bir öğeyi bir kerede bellekte saklama


İlk kod snippet'iniz hakkında arg 'stream' listesinden başka ne olabileceğini bilmek istiyorum []?
Iqra.

5

Her iki yaklaşımı da aynı veriler için karşılaştırabilirsiniz:

def myGeneratorList(n):
    for i in range(n):
        yield i

def myIterableList(n):
    ll = n*[None]
    for i in range(n):
        ll[i] = i
    return ll

# Same values
ll1 = myGeneratorList(10)
ll2 = myIterableList(10)
for i1, i2 in zip(ll1, ll2):
    print("{} {}".format(i1, i2))

# Generator can only be read once
ll1 = myGeneratorList(10)
ll2 = myIterableList(10)

print("{} {}".format(len(list(ll1)), len(ll2)))
print("{} {}".format(len(list(ll1)), len(ll2)))

# Generator can be read several times if converted into iterable
ll1 = list(myGeneratorList(10))
ll2 = myIterableList(10)

print("{} {}".format(len(list(ll1)), len(ll2)))
print("{} {}".format(len(list(ll1)), len(ll2)))

Ayrıca, bellek ayak izini kontrol ederseniz, jeneratör tüm değerleri aynı anda belleğe kaydetmeye gerek duymadığından çok daha az bellek alır.


1

Python'un yeni başlayanlar için çok basit bir şekilde yazıyorum, ancak Python'un derinliklerinde pek çok şey yapıyor.

Çok temel ile başlayalım:

Bir liste düşünün,

l = [1,2,3]

Eşdeğer bir işlev yazalım:

def f():
    return [1,2,3]

o / p / print(l): [1,2,3]& o / p /print(f()) : [1,2,3]

Listeyi tekrarlanabilir yapalım: Python listesinde her zaman yinelenebilir, bu da istediğiniz zaman yineleyici uygulayabileceğiniz anlamına gelir.

Şimdi yineleyiciyi listeye uygulayalım:

iter_l = iter(l) # iterator applied explicitly

Bir işlevi tekrarlanabilir hale getirelim, yani eşdeğer bir jeneratör işlevi yazalım. Anahtar kelimeyi tanıttığınız anda python'da yield; bir jeneratör işlevi haline gelir ve yineleyici dolaylı olarak uygulanır.

Not: Her jeneratörün her zaman üstü kapalı yineleyici uygulandığında tekrarlanabilir olması ve burada örtük yineleyicinin temel noktası Jeneratör işlevi şöyle olacaktır:

def f():
  yield 1 
  yield 2
  yield 3

iter_f = f() # which is iter(f) as iterator is already applied implicitly

Eğer gözlemlediyseniz, fa jeneratör işlevini yaptığınızda, zaten iter (f)

Şimdi,

l listedir, yineleyici yöntemi uyguladıktan sonra "iter" olur, iter (l)

f zaten iter (f) 'dir, iter yöntemi "iter" uygulandıktan sonra iter (iter (f)), tekrar iter (f)

Bu zaten int olan int (x) 'e döküm yapıyorsunuz ve int (x) olarak kalacak.

Örneğin:

print(type(iter(iter(l))))

dır-dir

<class 'list_iterator'>

Unutmayın, bu Python ve C veya C ++ değil

Dolayısıyla yukarıdaki açıklamadan çıkan sonuç şöyledir:

liste l ~ = iter (l)

üreteç işlevi f == iter (f)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.