Sonsuz bir üretici için bir ifade var mı?


119

Sonsuz elemanlar üretebilen düz bir üreteç ifadesi var mı?

Bu tamamen teorik bir sorudur. Burada "pratik" bir cevaba gerek yok :)


Örneğin, sonlu bir üretici yapmak kolaydır:

my_gen = (0 for i in xrange(42))

Bununla birlikte, sonsuz bir tane yapmak için ad alanımı sahte bir işlevle "kirletmem" gerekiyor:

def _my_gen():
    while True:
        yield 0
my_gen = _my_gen()

İşleri ayrı bir dosyada yapmak ve importdaha sonra yapmak sayılmaz.


Bunun itertools.repeattam olarak bunu yaptığını da biliyorum . O olmadan tek satırlık bir çözüm olup olmadığını merak ediyorum.


9
Aslında ad alanınızı kirletmenize gerek yok ... sadece işlevi adlandırın my_genve sonra yapın my_gen = my_gen().
6502

2
del _my_genikisini karıştırmak istemiyorsanız da kullanabilirsiniz
John La Rooy

Yanıtlar:


133
for x in iter(int, 1): pass
  • İki bağımsız değişken iter= sıfır bağımsız değişken çağrılabilir + sentinel değer
  • int() her zaman geri döner 0

Bu nedenle, iter(int, 1)sonsuz bir yineleyicidir. Açıkçası, bu özel tema üzerinde çok sayıda varyasyon var (özellikle lambdakarışıma eklediğinizde ). Özel notun bir varyantı, iter(f, object())yeni oluşturulmuş bir nesnenin, sentinel değerin, ilk argüman olarak kullanılan çağrılabilir özellikten bağımsız olarak neredeyse sonsuz bir yineleyiciyi garanti ettiği gibi kullanılmasıdır.


3
Birçok kez unuttuğumuz iterözelliği ile kullanmanın çok ilginç bir yolu int.
Senthil Kumaran

3
simüle etmek için bu sihirli tarifi kullanabilirsiniz itertools.count:count = lambda start=0, step=1: (start + i*step for i, _ in enumerate(iter(int, 1)))
Coffee_Table

1
Sadece burada neler olduğunu açıklamak için: Ne zaman itertaşımasının avantajlı iki argümanla çağrılır, normalde biraz farklı davranır: iter(callable, sentinel) -> iterator. Bağımsız değişken 1, değerini döndürene kadarcallable yineleyicinin her yinelemesi için çağrılır . Ancak, her zaman geri döneceğimiz gibi , sonsuza kadar arayabiliriz ve asla 1'e ulaşamayız. Bu aslında sonsuz bir 's listesi oluşturacaktırsentinelint()0int()0
Olsgaard

217

itertools üç sonsuz jeneratör sağlar:

Standart kitaplıkta başka birini bilmiyorum.


Tek satırlık istediğinden beri:

__import__("itertools").count()

18
Re: Tekrar (x, zamanlar = ∞) - hayır yoktur merak kim sembolü - argüman ihmal sonsuza dek tekrar çalışmasını yapar
Mr_and_Mrs_D

Olumlu oy verildi çünkü (ncoghlan'ın cevabı doğrudan OP'nin sorusuna hitap ederken) bu daha genel olarak uygulanabilir.
Huw Walters

Bu, büyülü sözlerden çok daha okunabilir bir şey iter(int, 1). Çok kötü , tek amacı bunu yapmak olan itertoolsbir endlessly()yönteme sahip değil ; itertools.count()hepsi de okunabilir değil.
BallpointBen

19

iter () 'in gözcüsünden her zaman farklı bir sabit döndüren bir çağrılabilir üzerinde yineleme yapabilirsiniz

g1=iter(lambda:0, 1)

8
Bunu hem seviyorum hem de nefret ediyorum ... İstediğimi bu kadar az karakterde başarmasını seviyorum, ama kimsenin ona bakıp ne yapması gerektiğini bilmemesinden nefret ediyorum.
ArtOfWarfare

1
iter(burada ekstra sentinel ile) sözdizimini ve sözdizimini lambda(burada hiçbir geçirilen parametre olmadan, sadece return 0) bilerek, nefret edilecek tek yer bu muammalı g1.
Sławomir Lenart

@ SławomirLenart erkekler bunu asla anlamaz. Sadece utanç verici derecede küçüktü, bu yüzden 1g fışkırttım.
user237419

8

İşletim sisteminiz sonsuz bir jeneratör olarak kullanılabilecek bir şey sağlayabilir. Örn. Linux üzerinde

for i in (0 for x in open('/dev/urandom')):
    print i

açıkçası bu kadar verimli değil

for i in __import__('itertools').repeat(0)
    print i

11
/ Dev / urandom çözümünün \nzaman zaman ortaya çıkmasına bağlı ... Dolandırıcı! :)
hugomg

5

Hiçbiri, sınıf / işlev / oluşturucu olarak tanımlanan başka bir sonsuz yineleyiciyi dahili olarak kullanmayan (ifade değil, bir işlev yield). Bir üreteç ifadesi her zaman yinelenebilir bir düzenleyiciden yararlanır ve öğelerini filtrelemek ve eşlemek dışında hiçbir şey yapmaz. Yalnızca mapve ile sonlu öğelerden sonsuz öğelere geçemezsiniz filter, ihtiyacınız olan while(veya forbu sona ermeyen, tam olarak yalnızca kullanamayacağımız şeydir)for ve sonlu yineleyicileri ).

Trivia: PEP 3142 yüzeysel olarak benzerdir, ancak daha yakından incelendiğinde hala formaddeyi gerektirdiği görülüyor (yani (0 while True)sizin için hayır ), yani sadece kısayol sağlıyor itertools.takewhile.


Şüphelendiğim gibi ... Kötüye kullanım için hazır bir sonsuz jeneratör olmadığından emin olabilir miyiz? (Ne yazık ki, xrange (0,1, -1) çalışmıyor ...)
hugomg

2
@missingno: from itertools import repeat, count, cyclemuhtemelen çoğu kişi için "hazır" olarak sayılır.
ncoghlan

1
Oops, 2 argümanı unuttum iter. Sonsuz yineleyiciler aslında yerleşik olarak mevcuttur
cevabıma

5

Oldukça çirkin ve çılgınca (yine de çok komik), ancak bazı hileler kullanarak bir ifadeden kendi yineleyicinizi oluşturabilirsiniz (ad alanınızı gerektiği gibi "kirletmeden"):

{ print("Hello world") for _ in
    (lambda o: setattr(o, '__iter__', lambda x:x)
            or setattr(o, '__next__', lambda x:True)
            or o)
    (type("EvilIterator", (object,), {}))() } 

Açıkça
LISP'yi

1
@Faissaloo Gerçekten ... Yazdığım eski bir sayfada daha da çılgınca bir ifade bulabilirsiniz: baruchel.github.io/python/2018/06/20/…
Thomas Baruchel

2

Belki bunun gibi dekoratörleri kullanabilirsiniz, örneğin:

def generator(first):
    def wrap(func):
        def seq():
            x = first
            while True:
                yield x
                x = func(x)
        return seq
    return wrap

Kullanım (1):

@generator(0)
def blah(x):
    return x + 1

for i in blah():
    print i

Kullanım (2)

for i in generator(0)(lambda x: x + 1)():
    print i

Bu çirkinlerden kurtulmanın daha da geliştirilebileceğini düşünüyorum (). Bununla birlikte, yaratmak istediğiniz dizinin karmaşıklığına bağlıdır. Genel olarak konuşursak, eğer sekansınız fonksiyonlar kullanılarak ifade edilebiliyorsa, jeneratörlerin tüm karmaşıklığı ve sözdizimsel şekeri bir dekoratör veya dekoratör benzeri bir fonksiyon içinde gizlenebilir.


9
OP bir oneliner ister ve sizde üçlü iç içe defve kapalı 10 satırlık bir dekoratör mü sunuyorsunuz ? ;)

2
@delnan Ama dekoratörü bir kez tanımlarsan, bir gömlek alabilirsin, değil mi? Anladığım kadarıyla amaç, her ek sonsuz jeneratörün tek bir hatta uygulanmasını sağlamak. Ve burada sunulan budur. Alabilirsin, (2^x)alabilirsin (x). Biraz iyileştirirseniz muhtemelen fibonacci, vb.
julx

Soruma cevap vermiyor, ama o zaman tüm bu kabarık kapanışları nasıl sevemezsin? BTW, seqdoğrudan wrap
koddan kurtarıp
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.