SORU
14 Mart 2012, ÇARŞAMBA


Uygulamada, yeni "" verim; Python 3.3 engelleyen başlıca kullanım alanları nelerdir?

PEP 380 etrafında sabit bir zaman beynimi sarma içiyorum.

  1. Bu durumlarda, "" yararlı mı? verim ne
  2. Klasik kullanım durumu nedir?
  3. Neden mikro-ipler karşılaştırılır?

Şimdiden teşekkürler!

[ güncelleme ]

Şimdi benim zorluklar nedeni anlıyorum. Jeneratörler kullandım ama hiç coroutines (PEP-342 tarafından kullanılmaya başlandı). Bazı benzerlikler rağmen, jeneratörler ve coroutines temelde iki farklı kavramlardır. Anlayış coroutines (sadece jeneratör) yeni sözdizimini anlamak için bir anahtardır.

IMHOcoroutines en karanlık Python özelliği vardıren kitaplar yararsız görünmesi ve ilginç.

Bu harika cevaplar için teşekkürler, ama agf zleri 56* *bağlantı için özel teşekkürler. David kayalar.

CEVAP
29 EYLÜL 2014, PAZARTESİ


Hadi bir şey olsun. yield from g for v in g: yield v eşdeğer bir açıklamahatta adalet yapmaya başlamıyorne için yield from. Çünkü, kabul edelim, eğer yield from mu genişletin for döngü, değil emri ekleme yield from Dil ve engel bir sürü yeni özellik olmaktan uygulanan Python 2.x.

Bir sağlama olarak yield from düşünyönlü iki kanallı şeffafsub-generator caller. Hem de içerirarasında veri almaveveri göndermek içinsub-generator. Eğer eminseniz değil BTW, nebir jeneratör veri göndermehatta her şeyi bir kenara bırakıp coroutines ilk okuma ile ilgili olarak yapmanız gerekir. Dave Beazley's Curious Course on Couroutines mükemmel bir başlangıç. Hızlı bir astar Read slides 24-33.

Bir jeneratör verimi kullanarak veri okuma

def reader():
    """A generator that fakes a read from a file, socket, etc."""
    for i in range(4):
        yield '<< %s' % i

def reader_wrapper(g):
    # Manually iterate over data produced by reader
    for v in g:
        yield v

wrap = reader_wrapper(reader())
for i in wrap:
    print(i)

# Result
<< 0
<< 1
<< 2
<< 3

Manuel olarak reader(), yineleme yerine sadece 23 ** yapabiliriz.

def reader_wrapper(g):
    yield from g

Bu çalışır ve kod satırı ortadan kaldırdık. Ve muhtemelen niyeti biraz daha nettir (ya da değil). Ama değişen hiçbir şey yok hayatım.

Bir jeneratör veri gönderme (coroutine) verim kullanarak - Kısım 1

Şimdi daha ilginç bir şey yapmak. Hadi veri gönderilen kabul eder ve bir yuva, fd, vb yazan bir coroutine writer oluşturun.

def writer():
    """A coroutine that writes data *sent* to it to fd, socket, etc."""
    while True:
        w = (yield)
        print('>> ', w)

Şimdi soru, nasıl bir sarıcı işlevi sarıcı gönderilen herhangi bir veri, böylece yazara gönderme verileri işlemek gerekirşeffafgönderilen writer()?

def writer_wrapper(coro):
    # TBD
    pass

w = writer()
wrap = writer_wrapper(w)
wrap.send(None)  # "prime" the coroutine
for i in range(4):
    wrap.send(i)

# Expected result
>>  0
>>  1
>>  2
>>  3

Sarıcı gerekiyorkabuldöngü için yetersiz kaldığında, (belli ki) gönderilen ve aynı zamanda StopIteration işlemesi gereken veri. Sadece for x in coro: yield x yapmaya yetmez besbelli. Burada çalışan bir versiyonu.

def writer_wrapper(coro):
    coro.send(None)  # prime the coro
    while True:
        try:
            x = (yield)  # Capture the value that's sent
            coro.send(x)  # and pass it to the writer
        except StopIteration:
            pass

Ya da, bunu yapabiliriz.

def writer_wrapper(coro):
    yield from coro

Kod 6 satır, çok daha okunabilir hale getirmek kaydeder ve çok işe yarıyor. Sihirli!

- Part 2 - İstisna işleme jeneratör verim için veri gönderme

Hadi biraz karışık bir durum. Eğer yazarımız özel durumları ele almak gerekiyor yoksa? Hadi writer SpamException kolları ve eğer karşılaşırsa *** yazdırır.

class SpamException(Exception):
    pass

def writer():
    while True:
        try:
            w = (yield)
        except SpamException:
            print('***')
        else:
            print('>> ', w)

Eğer writer_wrapper değişiklik yok eğer doğru değilse ne? İşe yarıyor mu? Bir deneyelim

# writer_wrapper same as above

w = writer()
wrap = writer_wrapper(w)
wrap.send(None)  # "prime" the coroutine
for i in [0, 1, 2, 'spam', 4]:
    if i == 'spam':
        wrap.throw(SpamException)
    else:
        wrap.send(i)

# Expected Result
>>  0
>>  1
>>  2
***
>>  4

# Actual Result
>>  0
>>  1
>>  2
Traceback (most recent call last):
  ... redacted ...
  File ... in writer_wrapper
    x = (yield)
__main__.SpamException

Um, x = (yield) sadece özel durum oluşturur ve her şey çökmesini durma noktasına geliyor çünkü işe yaramıyor. Hadi yap bunu, ama el ile, özel durumları ve bunları gönderme ya da alt-Jeneratör (writer) içine atma

def writer_wrapper(coro):
    """Works. Manually catches exceptions and throws them"""
    coro.send(None)  # prime the coro
    while True:
        try:
            try:
                x = (yield)
            except Exception as e:   # This catches the SpamException
                coro.throw(e)
            else:
                coro.send(x)
        except StopIteration:
            pass

Bu çalışıyor.

# Result
>>  0
>>  1
>>  2
***
>>  4

Ama tabi bu da!

def writer_wrapper(coro):
    yield from coro

yield from şeffaf değerleri gönderme veya alt-jeneratör değerleri içine atma işler.

Bu hala tüm köşe olgulara kapsamaz. Eğer dış jeneratör kapalı ise ne olacak? Sub-jeneratör değeri (Evet, python 3, jeneratörler dönüş değerler) geldiğinde durum ne olacak, nasıl bir dönüş değeri dağıtılmasını? All the corner cases that yield from handles transparently is really impressive. yield from sihirli bir şekilde çalışıyor ve tüm bu davalara bakan.

Ben şahsen yield from yapmaz çünkü kötü kelime bir seçim olduğunu hissediyorumiki yönlüdoğa belli. Diğer anahtar kelimeler önerilen (delegate gibi ama diline yeni bir kelime birleştirerek çok daha zordur çünkü ekleme reddedildi.

Özet olarak, düşünmek için elinden geleni 49 ** gibitransparent two way channelcaller sub-generator arasında.

Referanslar:

  1. PEP 380 - alt-jeneratör temsilciliği için Sözdizimi (Ewing) [v3.3, 2009-02-13]
  2. PEP 342 - Gelişmiş Jeneratörler () GvR, Algılama [v2.Coroutines)5, 2005-05-10]

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Autodesk 3ds Max Learning Channel

    Autodesk 3ds

    23 HAZİRAN 2010
  • Perihelion

    Perihelion

    23 NİSAN 2008
  • Tina Chen

    Tina Chen

    26 Mayıs 2012