Python yineleyicilerinin bir hasNext
yöntemi yok mu?
Python yineleyicilerinin bir hasNext
yöntemi yok mu?
Yanıtlar:
Hayır, böyle bir yöntem yok. Yinelemenin sonu bir istisna ile gösterilir. Belgelere bakın .
unnext()
arayarak var olduğunu kontrol ettikten sonra ilk eleman geri koymak için bir yöntem olsaydı ben try catch çözüm kabul ediyorum next()
.
yield
bilmiyorsunuz). Depolar sonucu olduğunu O, elbette, zor değil bir adaptör yazmaya edilir next()
ve sağlar has_next()
ve move_next()
.
hasNext()
yöntemi uygulamak için de kullanılabilir (üretmek için önbelleğe almak ve başarı üzerine true döndürmek veya başarısız olduğunda false döndürmek). Sonra iki hasNext()
ve next()
altta yatan bir ortak bağlı olacağını getNext()
yöntem ve önbelleğe öğeyi. Bunu next()
sağlayan bir bağdaştırıcıyı uygulamak çok kolaysa, neden standart kitaplıkta olmamalı gerçekten görmüyorum .
next()
ve hasNext()
yöntemini de etkiler ). Bu yüzden evet next()
ve hasNext()
taranan akışın içeriği öğelerin ne zaman okunduğuna bağlıysa zorlaşır.
StopIteration
Kullanarak bir alternatif var next(iterator, default_value)
.
Exapmle için:
>>> a = iter('hi')
>>> print next(a, None)
h
>>> print next(a, None)
i
>>> print next(a, None)
None
Böylece None
, istisna yolunu istemiyorsanız, yineleyicinin sonu için önceden belirlenmiş başka bir değer tespit edebilirsiniz .
sentinel = object()
ve next(iterator, sentinel)
birlikte ve testi is
.
unittest.mock.sentinel
Eğer açık bir yazmasına olanak tanır nesne next(a, sentinel.END_OF_ITERATION)
sonra veif next(...) == sentinel.END_OF_ITERATION
Eğer gerçekten varsa gerek bir has-next
(sadece sadakatle diyelim ki, Java referans uygulanmasından bir algoritma transkripsiyonu çünkü, yoksa bir prototip yazıyoruz çünkü işlevselliği olacak o bitince kolayca Java transkripsiyonu gerekir), bu kolaydır küçük bir sargı sınıfıyla elde edin. Örneğin:
class hn_wrapper(object):
def __init__(self, it):
self.it = iter(it)
self._hasnext = None
def __iter__(self): return self
def next(self):
if self._hasnext:
result = self._thenext
else:
result = next(self.it)
self._hasnext = None
return result
def hasnext(self):
if self._hasnext is None:
try: self._thenext = next(self.it)
except StopIteration: self._hasnext = False
else: self._hasnext = True
return self._hasnext
şimdi böyle bir şey
x = hn_wrapper('ciao')
while x.hasnext(): print next(x)
yayar
c
i
a
o
gereğince, gerektiği gibi.
Yerleşik next(sel.it)
olarak kullanımının Python 2.6 veya daha üstünü gerektirdiğini unutmayın; Python'un daha eski bir sürümünü kullanıyorsanız, self.it.next()
bunun yerine kullanın (ve next(x)
örnek kullanımda benzer şekilde ). [[Bu notun gereksiz olduğunu düşünebilirsiniz, çünkü Python 2.6 bir yıldan uzun bir süredir var - ancak Python 2.6 özelliklerini bir yanıtta kullandığımdan daha sık değil, bazı yorumcular veya başkaları işaret etmek zorunda kaldı onlar vardır , böylece bir kez ;-)]] için böyle bir yorum önlemek çalışıyorum, 2.6 özellikleri
has_next
yönteme ihtiyaç duymanın en kötü nedenidir . Python'un tasarımı, örneğin, filter
bir dizinin belirli bir yüklemle eşleşen bir öğe içerip içermediğini kontrol etmeyi imkansız hale getirir . Python topluluğunun kibir ve dar görüşlülüğü şaşırtıcı.
TypeError: iter() returned non-iterator
map
ve any
yerine kullanırsınız filter
, ancak a'yı kullanabilir SENTINEL = object(); next(filter(predicate, arr), SENTINEL) is not SENTINEL
veya unutabilir SENTINEL
ve sadece kullanın try: except
ve yakalayın StopIteration
.
StopIteration'ın tüm sözlerine ek olarak, Python "for" döngüsü istediğinizi yapar:
>>> it = iter("hello")
>>> for i in it:
... print i
...
h
e
l
l
o
Herhangi bir yineleyici nesnesinden __length_hint __ () yöntemini deneyin:
iter(...).__length_hint__() > 0
__init__
ve __main__
? Imho, haklı çıkarmaya çalışsanız da biraz karışıklık.
hasNext
bir şekilde StopIteration
istisna anlamına gelir, örneğin:
>>> it = iter("hello")
>>> it.next()
'h'
>>> it.next()
'e'
>>> it.next()
'l'
>>> it.next()
'l'
>>> it.next()
'o'
>>> it.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
StopIteration
dokümanlar: http://docs.python.org/library/exceptions.html#exceptions.StopIterationHayır. En benzer kavram büyük olasılıkla bir StopIteration istisnasıdır.
Python'un sadece next () olduğuna inanıyorum ve dokümana göre, daha fazla unsur olmadığı için bir istisna atıyor.
Beni aramaya yönlendiren kullanım durumu şudur:
def setfrom(self,f):
"""Set from iterable f"""
fi = iter(f)
for i in range(self.n):
try:
x = next(fi)
except StopIteration:
fi = iter(f)
x = next(fi)
self.a[i] = x
hasnext () kullanılabilir olduğunda,
def setfrom(self,f):
"""Set from iterable f"""
fi = iter(f)
for i in range(self.n):
if not hasnext(fi):
fi = iter(f) # restart
self.a[i] = next(fi)
ki bu bana daha temiz. Açıkçası, yardımcı sınıfları tanımlayarak sorunların üstesinden gelebilirsiniz, ancak o zaman olan şey, her biri tuhaflıkları olan yirmi tek farklı neredeyse eşdeğer geçici çözümün çoğalmasına sahip olmanız ve farklı geçici çözümler kullanan kodu yeniden kullanmak istiyorsanız, tek bir uygulamanızda birden fazla eşdeğeri varsa veya aynı yaklaşımı kullanmak için kodu alıp yeniden yazarak dolaşın. 'Bir kez yapın ve iyi yapın' maxim kötü bir şekilde başarısız olur.
Ayrıca, yineleyicinin bir istisna oluşturması gerekip gerekmediğini görmek için dahili bir 'hasnext' kontrolüne sahip olması gerekir. Bu iç kontrol daha sonra bir öğeyi almaya çalışarak, istisnayı yakalayarak ve atıldığında işleyiciyi çalıştırarak test edilmesi gereken şekilde gizlenir. Bu, IMO'yu gizlemek için gereksizdir.
Önerilen yol StopIteration . Lütfen tutorialspoint'ten Fibonacci örneğine bakın
#!usr/bin/python3
import sys
def fibonacci(n): #generator function
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(5) #f is iterator object
while True:
try:
print (next(f), end=" ")
except StopIteration:
sys.exit()
Sorunumu çözme şeklim, şimdiye kadar yinelenen nesnelerin sayısını korumaktır. Bir örnek yöntemi çağrıları kullanarak bir küme üzerinde yineleme yapmak istedim. Setin uzunluğunu ve şimdiye kadar sayılan öğelerin sayısını bildiğim için etkili bir hasNext
yöntemim vardı .
Kodumun basit bir sürümü:
class Iterator:
# s is a string, say
def __init__(self, s):
self.s = set(list(s))
self.done = False
self.iter = iter(s)
self.charCount = 0
def next(self):
if self.done:
return None
self.char = next(self.iter)
self.charCount += 1
self.done = (self.charCount < len(self.s))
return self.char
def hasMore(self):
return not self.done
Tabii ki, örnek bir oyuncak, ama fikri anladınız. Bu, bir jeneratör vb. Gibi tekrarlanabilir uzunluğun elde edilmesinin bir yolu olmadığı durumlarda işe yaramaz.