Örneğin, aşağıdaki gibi bir listemiz olsa, bu listenin boş olup olmadığını nasıl kontrol ederiz?
a = []
Kısa Cevap:
Listeyi bir boole bağlamına yerleştirin (örneğin, bir if
veya while
deyimiyle), sonuç False
ise boş, True
ise doludur.
if not a:
print('a boş bir liste')
PEP 8
Python’un standart kitaplığındaki Python kodu için resmi Python stil kılavuzu olan PEP 8 şunu söylüyor:
Dizilerin (dizeler, listeler, diziler)
False
olduğu gerçeğini kullanın.
Yes: if not seq:
if seq:
No: if len(seq):
if not len(seq):
Standart kitaplık kodunun mümkün olduğunca performanslı ve doğru olmasını beklemeliyiz. Ama neden durum bu ve neden bu rehberliğe ihtiyacımız var?
Açıklama
Python’da yeni olan deneyimli programcılardan sık sık böyle kodlar görebilirsiniz:
if len(a) == 0: # Bunu yapmayın
print('a boş bir liste')
Ve tembel dil kullanıcıları da bunu yapmak isteyebilir:
if a == []: # Bunu yapmayın
print('a boş bir liste')
Bunlar başka dillerde doğru olabilir. Ve Python’da da anlamsal olarak doğrudur.
Ancak pythonik olmadığını düşünüyoruz, çünkü Python semantik bir şekilde doğrudan boole zorlaması yoluyla liste nesnesini destekliyor.
Pythonik yöntemi kullanmak genellikle performansta karşılığını verir
Karşılığını veriyor mu? (Eşdeğer bir işlemi gerçekleştirmek için daha az süre daha iyidir)
>>> import timeit
>>> min(timeit.repeat(lambda: len([]) == 0, repeat=100))
0.13775854044661884
>>> min(timeit.repeat(lambda: [] == [], repeat=100))
0.0984637276455409
>>> min(timeit.repeat(lambda: not [], repeat=100))
0.07878462291455435
Ölçek için, boş bir liste oluşturmanın ve döndürmenin maliyeti aşağıda:
>>> min(timeit.repeat(lambda: [], repeat=100))
0.07074015751817342
Yerleşik işlevle uzunluğun denetlendiği, veya boş bir listeye karşı kontrol edildiği yöntemlerin çok daha az performanslı olduğunu görüyoruz.
Neden?
len(a) == 0
kontrolü için:
İlk olarak Python len
‘in varlığını kontrol etmek zorunda.
Ardından işlevi çağırmalı, yüklemeli ve Python’da eşitlik karşılaştırmasını yapmalı.
>>> import dis
>>> dis.dis(lambda: len([]) == 0)
1 0 LOAD_GLOBAL 0 (len)
2 BUILD_LIST 0
4 CALL_FUNCTION 1
6 LOAD_CONST 1 (0)
8 COMPARE_OP 2 (==)
10 RETURN_VALUE
[] == []
için ise önce gereksiz bir liste oluşturması ve ardından yine Python’un sanal makinesinde karşılaştırma işlemini yapması gerekir
>>> dis.dis(lambda: [] == [])
1 0 BUILD_LIST 0
2 BUILD_LIST 0
4 COMPARE_OP 2 (==)
6 RETURN_VALUE
Listenin uzunluğu nesnenin üstbilgisinde önbelleğe kaydedildiğinden “Pythonik” yolu çok daha basit ve hızlı bir denetim olacaktır:
>>> dis.dis(lambda: not [])
1 0 BUILD_LIST 0
2 UNARY_NOT
4 RETURN_VALUE