Python'da "yinelenebilir", "yineleyici" ve "yineleme" nin en temel tanımı nedir?
Birden fazla tanım okudum ama hala batmayacağı için kesin anlamı tanımlayamıyorum.
Birisi bana layman terimleriyle 3 tanım konusunda yardımcı olabilir mi?
Python'da "yinelenebilir", "yineleyici" ve "yineleme" nin en temel tanımı nedir?
Birden fazla tanım okudum ama hala batmayacağı için kesin anlamı tanımlayamıyorum.
Birisi bana layman terimleriyle 3 tanım konusunda yardımcı olabilir mi?
Yanıtlar:
Yineleme , bir şeyin her bir parçasını birbiri ardına almak için kullanılan genel bir terimdir. Bir öğe grubunun üzerinden geçmek için açık veya kapalı bir döngü kullandığınızda, bu yinelemedir.
Python'da yinelemeli ve yineleyicinin belirli anlamları vardır.
Bir iterable bir olan bir amacı, __iter__
kullanıcıya bir yöntem yineleyici veya tanımlar __getitem__
sıfırdan başlayarak ardışık indeksleri alabilir yöntemi (ve yükseltir IndexError
endeksler artık geçerli olduğu zaman). Yani bir yinelenebilir bir yineleyici alabileceğiniz bir nesnedir .
Bir yineleyici bir ile bir amacı, next
(Python 2) ya da __next__
(Python 3) yöntemi.
Python'da bir for
döngü map
veya bir liste kavrama vb. Kullandığınızda, next
her öğeyi yineleyiciden almak için yöntem otomatik olarak çağrılır , böylece yineleme işleminden geçer .
İyi bir yer olacağını öğrenmeye başlamak için öğretici yineleyiciler bölümü ve standart tipleri sayfanın yineleyici türleri bölümü . Temel bilgileri anladıktan sonra , İşlevsel Programlama NASIL belgesinin yineleyiciler bölümünü deneyin .
__len__
yinelemeye bağlı kalsın ki ? Bir şeyin uzunluğunu bilmek, onu tekrarlamanıza nasıl yardımcı olur?
__getitem__
.
{'a': 'hi', 'b': 'bye'}
2 uzunluğa sahiptir fakat 0, 1 veya 2 tarafından dizine edilemez
__iter__
yöntemi var. Jlh özellikle tanımlanabilir çünkü "yinelenen __getitem__
sıralı dizinler alabilir bir yöntem " tanımlanabilir çünkü nesneler atıfta olduğunu düşünüyorum .
İşte Python sınıflarını öğretirken kullandığım açıklama:
Bir ITERABLE:
for x in iterable: ...
veyaiter()
bununla arayabileceğiniz her şey bir ITERATOR döndürecektir: iter(obj)
veya__iter__
yeni bir ITERATOR döndüren bir nesne tanımlar veya __getitem__
dizinlenmiş arama için uygun bir yöntemi olabilir .Bir ITERATOR bir nesnedir:
__next__
yöntemle:
StopIteration
__iter__
geri dönen bir yöntemi olduğu anlamına gelir self
).Notlar:
__next__
Python 3'te yöntem yazıldığından next
Python 2'de venext()
, kendisine iletilen nesne üzerindeki bu yöntemi çağırır.Örneğin:
>>> s = 'cat' # s is an ITERABLE
# s is a str object that is immutable
# s has no state
# s has a __getitem__() method
>>> t = iter(s) # t is an ITERATOR
# t has state (it starts by pointing at the "c"
# t has a next() method and an __iter__() method
>>> next(t) # the next() function returns the next value and advances the state
'c'
>>> next(t) # the next() function returns the next value and advances
'a'
>>> next(t) # the next() function returns the next value and advances
't'
>>> next(t) # next() raises StopIteration to signal that iteration is complete
Traceback (most recent call last):
...
StopIteration
>>> iter(t) is t # the iterator is self-iterable
for
döngülerle ilgili olduğu ve 1. mermi "üzerinden dönme" olduğu için 1. mermi 2. mermi ile örtüşüyor gibi görünüyor . Bunları ele alabilir misiniz?
iter()
olarak" size geçebilir şey " iter()
"
Yukarıdaki cevaplar harika, ama gördüğüm şeylerin çoğu gibi, benim gibi insanlar için bu ayrımı vurgulamayın .
Ayrıca, insanlar daha __foo__()
önce "X yöntemi olan bir nesnedir" gibi tanımlamalar yaparak "çok Pythonic" alma eğilimindedir . Bu tür tanımlar doğrudur - ördek yazma felsefesine dayanır, ancak yöntemlere odaklanmak, konsepti basitliğinde anlamaya çalışırken aralarında olma eğilimindedir.
Ben de versiyonumu ekliyorum.
Doğal dilde,
Python'da,
yinelenebilir , basitçe ifade edilebilir, iterasyonda, örneğin bir for
döngü ile kullanılabileceği anlamına gelen, yinelenebilir bir nesnedir . Nasıl? Yineleyici kullanarak . Aşağıda açıklayacağım.
... yineleyici , yinelemenin gerçekte nasıl yapılacağını tanımlayan bir nesnedir - özellikle bir sonraki elemanın ne olduğu . Bu yüzden next()
yöntemi olmalı
.
Yineleyiciler , öğelerinin önceki çağrılarla tüketilip tüketilmediğine bakılmaksızın, __iter__()
yöntemlerinin aynı nesneyi ( self
) döndürdüğü ayrımıyla kendileri de yinelenebilir next()
.
Python yorumlayıcı for x in obj:
ifadeyi gördüğünde ne düşünüyor ?
Bak, bir
for
döngü. Yineleyici bir işe benziyor ... Hadi bir tane alalım. ... Buobj
adam var, hadi ona soralım."Bay
obj
, yinelemeniz var mı?" (... çağrılariter(obj)
, hangi çağrılarobj.__iter__()
, mutlu bir şekilde yeni bir yineleyici dağıtır_i
.)Tamam, bu kolaydı ... Hadi tekrarlamaya başlayalım. (
x = _i.next()
...x = _i.next()
...)
Bay obj
bu testi başardığından (geçerli bir yineleyici döndüren belirli bir yöntemle), onu sıfatla ödüllendiriyoruz: Artık ona "tekrarlanabilir Bay obj
" diyebilirsiniz .
Bununla birlikte, basit durumlarda, normalde ayrı ayrı yineleyici ve yinelenebilir olmaktan yararlanamazsınız. Yani sadece kendi nesnesini oluşturan tek bir nesne tanımlarsınız . (Python, _i
dağıttığı obj
şeyin o kadar parlak değil, sadece obj
kendisinin olduğunu umursamıyor .)
Bu yüzden gördüğüm çoğu örnekte (ve beni tekrar tekrar kafa karıştırıcı olan şeylerde) görebilirsiniz:
class IterableExample(object):
def __iter__(self):
return self
def next(self):
pass
onun yerine
class Iterator(object):
def next(self):
pass
class Iterable(object):
def __iter__(self):
return Iterator()
Bununla birlikte, yineleyicinin yinelemeden ayrılmasından yararlanabileceğiniz durumlar vardır, örneğin bir satır öğeye sahip olmak istediğinizde, ancak daha fazla "imleç". Örneğin, "mevcut" ve "gelecek" öğelerle çalışmak istediğinizde, her ikisi için de ayrı yineleyiciler olabilir. Veya büyük bir listeden çeken birden fazla iş parçacığı: her öğenin tüm öğelerin üzerinden geçmek için kendi yineleyicisi olabilir. Bkz @ Raymond ve @ glglgl en yukarıdaki cevapları.
Ne yapabileceğinizi hayal edin:
class SmartIterableExample(object):
def create_iterator(self):
# An amazingly powerful yet simple way to create arbitrary
# iterator, utilizing object state (or not, if you are fan
# of functional), magic and nuclear waste--no kittens hurt.
pass # don't forget to add the next() method
def __iter__(self):
return self.create_iterator()
Notlar:
Tekrar edeceğim: yineleyici yinelenemez . Yineleyici for
döngüde "kaynak" olarak kullanılamaz . Ne for
döngü öncelikle ihtiyacı olan __iter__()
(o döner bir şey next()
).
Tabii ki, for
tek yineleme döngüsü değildir, bu yüzden yukarıdaki diğer bazı yapılar için de geçerlidir ( while
...).
Yineleyiciler next()
yinelemeyi durdurmak için StopIteration'ı atabilir. Bununla birlikte, sonsuza kadar tekrarlayabilir veya başka araçlar kullanabilir.
Yukarıdaki "düşünce sürecinde" _i
gerçekte mevcut değildir. Ben bu ismi uydurdum.
Python 3.x'te küçük bir değişiklik var: next()
yöntem (yerleşik değil) çağrılmalıdır __next__()
. Evet, başından beri böyle olmalıydı.
Ayrıca şöyle düşünebilirsiniz: yinelenebilir veriler var, yineleyici bir sonraki öğeyi çekiyor
Feragatname: Herhangi bir Python tercümanı geliştiricisi değilim, bu yüzden tercümanın ne düşündüğünü gerçekten bilmiyorum. Yukarıdaki yazılar sadece bir Python newbie'nin diğer açıklamalar, deneyler ve gerçek yaşam deneyimlerinden konuyu nasıl anladığımı gösteriyor.
for
döngünün yineleyiciye ihtiyacı olduğunu düşündüğünü sanıyordum ("Bak, bir döngü için. Bir yineleyici için bir iş gibi görünüyor ... Bir tane alalım."). Ama sonra sonunda notlarda "Yineleyici bir for
döngüde kaynak olarak kullanılamaz " diyorsunuz ...?
pass
bu next
tanımların kodunu koydunuz ? Birisinin bir sonrakini elde etmenin bir yolunu uygulaması gerektiği anlamına geldiğini varsayacağım.
pass
için .)
pass
, sözdizimsel nedenlerden dolayı orada olduğunu düşünüyorum. Ben sadece oldukça ilginç olan üç nokta nesnesinde cevaplar koştu : ...
"sonra yapılacak" bloğu belirtmek için kullanabilirsiniz . NotImplemented
de mevcuttur.
for
döngüde "kaynak" olarak kullanılamaz . Cevabınızı anladım ve aksi halde beğendim, ancak bence bunu düzeltmekten faydalanacaktır.
Yinelenebilir bir __iter__()
yöntemi olan bir nesnedir . Muhtemelen list()
s ve tuple()
s gibi birkaç kez yinelenebilir .
Yineleyici, yinelenen nesnedir. Bir __iter__()
yöntemle döndürülür , kendi __iter__()
yöntemiyle kendini döndürür ve bir next()
yöntemi vardır ( __next__()
3.x'te).
Yineleme, buna saygı verme sürecidir next()
. __next__()
yükselene kadar StopIteration
.
Misal:
>>> a = [1, 2, 3] # iterable
>>> b1 = iter(a) # iterator 1
>>> b2 = iter(a) # iterator 2, independent of b1
>>> next(b1)
1
>>> next(b1)
2
>>> next(b2) # start over, as it is the first call to b2
1
>>> next(b1)
3
>>> next(b1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> b1 = iter(a) # new one, start over
>>> next(b1)
1
Iterable
.
Iterator
her zaman Iterable
ve kendi olduğu Iterator
bir iki çağrıları iter()
mutlaka iki bağımsız vermeyin Iterator
s.
İşte benim hile sayfası:
sequence
+
|
v
def __getitem__(self, index: int):
+ ...
| raise IndexError
|
|
| def __iter__(self):
| + ...
| | return <iterator>
| |
| |
+--> or <-----+ def __next__(self):
+ | + ...
| | | raise StopIteration
v | |
iterable | |
+ | |
| | v
| +----> and +-------> iterator
| ^
v |
iter(<iterable>) +----------------------+
|
def generator(): |
+ yield 1 |
| generator_expression +-+
| |
+-> generator() +-> generator_iterator +-+
Test: Nasıl olduğunu görüyor musun ...
__iter__()
yöntemi bir jeneratör olarak uygulanabilir?__next__
mutlaka bir yineleyici değildir?Yanıtlar:
__iter__
yöntemi olmalıdır . Sahip __iter__
olmak yinelenebilir bir şey olmak için yeterlidir. Bu nedenle her yineleyici bir yinelenebilir.Zaman __iter__
denir bu (bir yineleyici döndürmelidir return <iterator>
diyagram yukarıda). Bir jeneratörü çağırmak, bir yineleyici türü olan bir jeneratör yineleyicisini döndürür.
class Iterable1:
def __iter__(self):
# a method (which is a function defined inside a class body)
# calling iter() converts iterable (tuple) to iterator
return iter((1,2,3))
class Iterable2:
def __iter__(self):
# a generator
for i in (1, 2, 3):
yield i
class Iterable3:
def __iter__(self):
# with PEP 380 syntax
yield from (1, 2, 3)
# passes
assert list(Iterable1()) == list(Iterable2()) == list(Iterable3()) == [1, 2, 3]
İşte bir örnek:
class MyIterable:
def __init__(self):
self.n = 0
def __getitem__(self, index: int):
return (1, 2, 3)[index]
def __next__(self):
n = self.n = self.n + 1
if n > 3:
raise StopIteration
return n
# if you can iter it without raising a TypeError, then it's an iterable.
iter(MyIterable())
# but obviously `MyIterable()` is not an iterator since it does not have
# an `__iter__` method.
from collections.abc import Iterator
assert isinstance(MyIterable(), Iterator) # AssertionError
__iter__
yöntemi olduğu gibi tekrarlanabilir hale gelir . Lütfen bu cevabı düzenleyerek 2. ve 3. noktalarda ayrıntılar verebilir
__iter__()
bir yineleyici döndürür. Bir jeneratör bir yineleyicidir, bu nedenle bu amaç için kullanılabilir. re 3 .: Ben sadece burada tahmin edebilirsiniz, ama sanırım __iter__()
eksik veya geri dönmezse self
, bir yineleyici değildir, çünkü bir yineleyici __iter__()
geri dönmek zorunda self
.
Kimseye yardım edip etmediğini bilmiyorum ama her zaman kafamdaki kavramları daha iyi anlamak için görselleştirmek isterim. Küçük bir oğlum olduğu için, yinelenebilir / yineleyici konseptini tuğla ve beyaz kağıtla görselleştiriyorum.
Karanlık odada olduğumuzu ve yerde oğlum için tuğla olduğunu varsayalım. Farklı boyutta, renkte tuğlalar artık önemli değil. Diyelim ki bunlar gibi 5 tuğla var. Bu 5 tuğla bir nesne olarak tanımlanabilir - diyelim ki tuğla kiti . Bu tuğla kiti ile birçok şey yapabiliriz - bir tane alabilir ve sonra ikinci ve daha sonra üçüncü olabilir, tuğla yerlerini değiştirebilir, ilk tuğlayı ikincinin üzerine koyabiliriz. Bunlarla pek çok şey yapabiliriz. Bu nedenle, bu tuğla kiti, her tuğlayı geçip onunla bir şeyler yapabileceğimiz için yinelenebilir bir nesne veya dizidir . Bunu sadece küçük oğlum gibi yapabiliriz - her seferinde bir tuğla ile oynayabiliriz . Tekrar kendimi bu tuğla kitinin biryinelenebilir .
Şimdi karanlık odada olduğumuzu hatırla. Ya da neredeyse karanlık. Aka - şey açıkça bu tuğlaları görmüyorum, onlar ne renk, ne onlarla bir şeyler yapmak istiyorum Yani bile vb şekil yineleme içlerinden - biz gerçekten bunun neyi nasıl olduğu için bilmiyorum çok karanlık.
Yapabileceğimiz ilk tuğlaya yakın - bir tuğla kitinin unsuru olarak - ilk tuğla elemanının nerede olduğunu görmemiz için bir parça beyaz floresan kağıt koyabiliriz. Ve bir kitten bir tuğla aldığımızda, karanlık odada bunu görebilmek için beyaz kağıt parçasını bir sonraki tuğlaya değiştiriyoruz. Bu beyaz kağıt bir yineleyiciden başka bir şey değildir . O da bir nesnedir . Ancak, tekrarlanabilir nesne - tuğla kitimizin unsurlarıyla çalışabileceğimiz ve oynayabileceğimiz bir nesne.
Bu arada aşağıdakileri bir IDLE'de denediğimde ve TypeError aldığımda ilk hatamı açıklıyor:
>>> X = [1,2,3,4,5]
>>> next(X)
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
next(X)
TypeError: 'list' object is not an iterator
Liste X burada bizim tuğla kitimizdi ama beyaz bir kağıt parçası değildi. Önce bir yineleyici bulmam gerekiyordu:
>>> X = [1,2,3,4,5]
>>> bricks_kit = [1,2,3,4,5]
>>> white_piece_of_paper = iter(bricks_kit)
>>> next(white_piece_of_paper)
1
>>> next(white_piece_of_paper)
2
>>>
Yardım edip etmediğini bilmiyorum, ama bana yardımcı oldu. Birisi kavramın görselleştirilmesini teyit edebilir / düzeltebilseydi minnettar olurum. Daha fazla bilgi edinmeme yardımcı olur.
İterable : - iterable iterable olduğu şey; listeler, dizeler gibi diziler gibi. Ayrıca __getitem__
yöntem veya __iter__
yöntem vardır. Şimdi iter()
bu nesne üzerinde işlev kullanırsak , bir yineleyici alırız.
Yineleyici : - Fonksiyondan iterator nesnesini aldığımızda iter()
; dediğimiz __next__()
sadece (python3 olarak) yöntemini veya next()
elemanları birer birer almak için (python2 olarak). Bu sınıfa veya bu sınıfın örneğine yineleyici denir.
Dokümanlar'dan: -
Yineleyicilerin kullanımı Python'u sarar ve birleştirir. Perde arkasında, for ifadesi iter()
container nesnesini çağırır . İşlev __next__()
, kaptaki öğelere birer birer erişen yöntemi tanımlayan bir yineleyici nesnesi döndürür . Başka öğe olmadığında __next__()
, for döngüsünün sonlanmasını bildiren bir StopIteration istisnası yükseltir. Yerleşik işlevi __next__()
kullanarak yöntemi çağırabilirsiniz next()
; bu örnek her şeyin nasıl çalıştığını gösterir:
>>> s = 'abc'
>>> it = iter(s)
>>> it
<iterator object at 0x00A1DB50>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
next(it)
StopIteration
Sınıf dışı: -
class Reverse:
"""Iterator for looping over a sequence backwards."""
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
>>> rev = Reverse('spam')
>>> iter(rev)
<__main__.Reverse object at 0x00A1DB50>
>>> for char in rev:
... print(char)
...
m
a
p
s
Belgelere göre çok daha basit olabileceğini sanmıyorum , ancak deneyeceğim:
Sen düşünebiliriz yineleyici sonraki (veya ilk) öğesini verir (veya tutar) bir yardımcı sözde yöntemi (veya sözde özniteliği) olarak iterable . (Uygulamada sadece yöntemi tanımlayan bir nesnedir next()
)
Yineleme muhtemelen en iyi kelimesinin Merriam-Webster tanımıyla açıklanır :
b: bir dizi bilgisayar talimatının belirli bir sayıda veya bir koşul karşılanana kadar tekrarlanması - özyinelemeyi karşılaştırın
iterable = [1, 2]
iterator = iter(iterable)
print(iterator.__next__())
print(iterator.__next__())
yani,
iterable
üzerinde döngü yapılabilen bir nesnedir . list, string, tuple vb.
kullanarak iter
bizim üzerinde işlev iterable
nesnesinin bir dönecektir yineleyici nesne.
Şimdi bu yineleyici nesne yöntemi seçti __next__
(Python 3'te, ya da sadece next
sen hangi tarafından Python 2'de) iterable her bir öğesini erişin.
bu nedenle, ÜST KODUN ÇIKIŞI:
1
2
Yinelemelerin
__iter__
her seferinde yeni bir yineleyici başlatan bir yöntemi vardır.Tekrarlayıcılar bir uygulamaya
__next__
tek tek öğeleri döndürür metodu ve bir__iter__
döndürdüğü yöntemiself
.Bu nedenle, yineleyiciler de yinelenebilir, ancak yineleyiciler yineleyiciler değildir.
Luciano Ramalho, Akıcı Python.
Yinelenebilirler ve yineleyici ile uğraşmadan önce yinelenebilir ve yineleyiciye karar veren ana faktör dizidir
Sıra: Sıra veri toplamadır
Yinelenebilir: Yinelenebilir, __iter__
yöntemi destekleyen dizi türü nesnedir .
Iter yöntemi: Iter yöntemi diziyi girdi olarak alır ve yineleyici olarak bilinen bir nesne oluşturur
Yineleyici: Yineleyici, sonraki yöntemi çağıran ve sıra boyunca enine olan nesnedir. Bir sonraki yöntemi çağırdığınızda, o anda gezdiği nesneyi döndürür.
misal:
x=[1,2,3,4]
x, veri toplanmasını içeren bir dizidir
y=iter(x)
Çağrı üzerinde iter(x)
, X amacı, o zaman y böyle atama olduğunu yineleyici döndüren bir exception.If yükseltmek aksi iter yöntemi vardır, sadece bir yineleyici verir:
y=[1,2,3,4]
Y bir yineleyici olduğu için destekleme next()
yöntemi
Bir sonraki yöntemi çağırdığınızda, listenin tek tek öğelerini tek tek döndürür.
Dizinin son öğesini döndürdükten sonra bir sonraki yöntemi çağırırsak, bir StopIteration hatası oluşturur
misal:
>>> y.next()
1
>>> y.next()
2
>>> y.next()
3
>>> y.next()
4
>>> y.next()
StopIteration
Python'da her şey bir nesnedir. Bir nesnenin yinelenebilir olduğu söylenirse, bu nesneyi bir koleksiyon olarak atabileceğiniz (yani yineleyebileceğiniz) anlamına gelir.
Örneğin diziler yinelenebilir. Bir for döngüsü ile bunlara adım atabilir ve dizin nesnesinin uzunluğu eksi 1 olmak üzere dizin 0'dan dizin n'ye gidebilirsiniz.
Sözlükler (ilişkilendirilebilir diziler olarak da adlandırılan anahtar / değer çiftleri) de yinelenebilir. Anahtarları arasında gezinebilirsiniz.
Açıkçası koleksiyon olmayan nesneler yinelenemez. Örneğin, bir bool nesnesinin yalnızca bir değeri vardır, Doğru veya Yanlış. Yinelenebilir değil (yinelenebilir bir nesne olduğu mantıklı olmaz).
Daha fazla oku. http://www.lepus.org.uk/ref/companion/Iterator.xml
iter()
ve standart koleksiyon türlerini çağırarak oluşturulan yineleyici nesneler yinelenebilir ancak kendileri koleksiyon değildir.
collections.abc.AsyncIterator
için testler__aiter__
ve__anext__
yöntemler. Bu 3.6'da yeni bir ektir.