Try-exclude bloğu ile python "with" ifadesini kullanma


99

Python "with" ifadesini bir try-exclude bloğu ile birlikte kullanmanın doğru yolu bu mu ?:

try:
    with open("file", "r") as f:
        line = f.readline()
except IOError:
    <whatever>

Eğer öyleyse, bir şeyleri yapmanın eski yöntemini düşünün:

try:
    f = open("file", "r")
    line = f.readline()
except IOError:
    <whatever>
finally:
    f.close()

Buradaki "ile" ifadesinin birincil faydası, üç satır koddan kurtulabilmemiz mi? Bu kullanım durumu için bana o kadar zorlayıcı görünmüyor ("with" ifadesinin başka kullanımları olduğunu anladığım halde).

DÜZENLEME: Yukarıdaki iki kod bloğunun işlevselliği aynı mı?

DÜZENLEME2: İlk birkaç cevap genellikle "with" kullanmanın faydalarından bahsediyor, ancak bunlar burada marjinal fayda sağlıyor gibi görünüyor. Yıllardır hepimiz açıkça f.close () çağrısı yapıyoruz (veya olmalıydık). Sanırım bir yararı, özensiz kodlayıcıların "with" kullanmanın faydasını görecek olmasıdır.



Benim için, bir nihayet ifadesinde bir şeyleri kapatmayı () hatırlamak zorunda olmamak, 'with' kullanmak için yeterince iyi bir nedendir. Kaynaklarını kapatmakta başarısız olan çok sayıda kod gördüm. Ve görebildiğim kadarıyla 'ile' dezavantajları yok.
Raúl Salinas-Monteagudo

Yanıtlar:


143
  1. Verdiğiniz iki kod bloğu eşdeğer değil
  2. Bir şeyleri yapmanın eski yolu olarak tanımladığınız kodun ciddi bir hatası var: dosyayı açmanın başarısız olması durumunda, finallycümlecikte ikinci bir istisna elde edeceksiniz çünkü fbağlı değil.

Eşdeğer eski stil kodu şöyle olacaktır:

try:
    f = open("file", "r")
    try:
        line = f.readline()
    finally:
        f.close()
except IOError:
    <whatever>

Gördüğünüz gibi withifade, işleri hataya daha az eğilimli hale getirebilir. Python'un (2.7, 3.1) daha yeni sürümlerinde, birden çok ifadeyi tek bir withifadede birleştirebilirsiniz . Örneğin:

with open("input", "r") as inp, open("output", "w") as out:
    out.write(inp.read())

Bunun yanı sıra, kişisel olarak herhangi bir istisnayı olabildiğince erken yakalamayı kötü bir alışkanlık olarak görüyorum. İstisnaların amacı bu değildir. Başarısız olabilen GÇ işlevi daha karmaşık bir işlemin parçasıysa, çoğu durumda IOError tüm işlemi iptal etmeli ve bu nedenle dış düzeyde ele alınmalıdır. withİfadeleri kullanarak , tüm bu try...finallyifadelerden iç seviyelerde kurtulabilirsiniz .


7

finallyBloğun içeriği, açılmakta olan dosya nesnesinin özelliklerine göre belirlenirse, neden finallybloğu yazan dosya nesnesinin uygulayıcısı olmasın ? İfadenin faydası budurwith , bu belirli durumda size üç satır kod tasarrufu sağlamaktan çok daha fazlasıdır.

Ve evet, birleştirme şekliniz withve try-exceptbunu yapmanın hemen hemen tek yolu, çünkü openifadenin kendisinde meydana gelen istisnai hatalar withblok içinde yakalanamaz .


1

Sanırım sadece çizgileri azalttığı "with" ifadesini yanlış anladınız. Aslında başlatma ve sökme işlemlerini gerçekleştirir.

Sizin durumunuzda "with"

  • bir dosya aç,
  • içeriğini işlemek ve
  • kapattığınızdan emin olun.

"With" ifadesini anlamak için bağlantı: http://effbot.org/zone/python-with-statement.htm

Düzenleme: Evet, "with" kullanımınız doğrudur ve her iki kod bloğunun işlevselliği aynıdır. Neden "with" kullanılacağıyla ilgili soru? bununla elde ettiğiniz faydalar yüzünden. yanlışlıkla f.close () eksikliğinden bahsettiğiniz gibi.


-4

Aşağıdaki kodlar için daha Pythonic yolu şudur:

try:
    f = open("file", "r")
    try:
        line = f.readline()
    finally:
        f.close()
except IOError:
    <whatever>

try:
    f = open("file", "r")
except IOError:
    <whatever>
else:
    f.close()

1
Sizin için kod biçimlendirmesi ekledim; okumayı kolaylaştırır. Ancak girintiyi bozmadığımdan emin olmak için iki kez kontrol etmek isteyebilirsiniz.
andrewsi

2
Hayır, sürümünüz orijinal kodla aynı şeyi yapmaz. Eksik readline()çağrıyı ekleseniz bile , sürümünüz dosyayı kapatmazsa readline()sonuç bir IOError.
Aleksi Torhamo
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.