Enumerate () ne anlama geliyor?


Yanıtlar:


513

enumerate()Fonksiyon bir iterable için bir sayaç ekler.

Yani cursoriçerideki her eleman için bir tuple üretilir (counter, element); fordöngü bağlandığı bu row_numberve rowsırasıyla.

Demo:

>>> elements = ('foo', 'bar', 'baz')
>>> for elem in elements:
...     print elem
... 
foo
bar
baz
>>> for count, elem in enumerate(elements):
...     print count, elem
... 
0 foo
1 bar
2 baz

Varsayılan olarak, enumerate()saymaya başlar, 0ancak buna ikinci bir tam sayı argümanı verirseniz, bunun yerine bu sayıdan başlar:

>>> for count, elem in enumerate(elements, 42):
...     print count, elem
... 
42 foo
43 bar
44 baz

enumerate()Python'da yeniden uygulayacak olsaydınız, bunu başarmanın iki yolu var; biri itertools.count()sayma işlemini yapmak için, diğeri bir jeneratör fonksiyonunda manuel sayma :

from itertools import count

def enumerate(it, start=0):
    # return an iterator that adds a counter to each element of it
    return zip(count(start), it)

ve

def enumerate(it, start=0):
    count = start
    for elem in it:
        yield (count, elem)
        count += 1

C gerçek uygulaması ortak tek bir demet nesnesini yeniden yakın ikincisine, optimizasyonlar ile for i, ...olan (durum açma ve karşı bir Python tamsayı nesnesini kullanarak engellemek için çok büyük hale gelene kadar sayaç için standart bir C tam sayı değeri ile sınırsız).


92

Üzerinde yinelenebilen bir nesne döndüren yerleşik bir işlevdir. Belgelere bakın .

Kısacası, bir yinelenebilir öğenin (bir liste gibi) öğelerinin yanı sıra bir demet halinde birleştirilmiş bir dizin numarasının üzerinden geçer:

for item in enumerate(["a", "b", "c"]):
    print item

baskılar

(0, "a")
(1, "b")
(2, "c")

Bir sekans (veya başka bir yinelenebilir şey) üzerinde döngü yapmak ve ayrıca bir indeks sayacını kullanmak istiyorsanız yararlıdır. Sayacın başka bir değerden (genellikle 1) başlamasını istiyorsanız, bunu ikinci argüman olarak verebilirsiniz enumerate.


1
ikinci bir değişken eklerseniz itemparantezleri kaldırabilirsiniz: D
Abdelouahab

2
Bilgiçlik: Bu bir yineleyici döndüren bir işlevdir, bir üreteci değil. Jeneratörler, kullanıcı tanımlı özel bir sınıftır ( örtük olarak yield/ yield fromveya jeneratör ifadeleri kullanarak yield); enumeratebir jeneratör değil. Ördek yazmayla ilgili tüm amaçlar için hiçbir fark yoktur, ancak açık tür denetimi ve Python dil dokümanları, kapsamı olmayan bir amaç için yalnızca "jeneratör" terimini kullanır enumerate.
ShadowRanger

22

Ben Brett Slatkin tarafından bir kitap ( Etkili Python ) okuyorum ve o bir liste üzerinde yineleme ve aynı zamanda listedeki geçerli öğenin dizinini bilmek için başka bir yol gösterir ama o kullanmak ve enumeratebunun yerine kullanmak daha iyi olduğunu önerir . Numaralandırmanın ne anlama geldiğini sorduğunuzu biliyorum, ancak aşağıdakileri anladığımda enumerate, mevcut öğenin dizinini daha kolay (ve daha okunabilir) bilirken bir liste üzerinde yinelemenin nasıl yapıldığını da anladım .

list_of_letters = ['a', 'b', 'c']
for i in range(len(list_of_letters)):
    letter = list_of_letters[i]
    print (i, letter)

Çıktı:

0 a
1 b
2 c

Ayrıca bir şey yapıyordum, enumeratefonksiyon hakkında okumadan önce daha da kirli .

i = 0
for n in list_of_letters:
    print (i, n)
    i += 1

Aynı çıktıyı üretir.

Ama enumerateben sadece yazmak zorundayım:

list_of_letters = ['a', 'b', 'c']
for i, letter in enumerate(list_of_letters):
    print (i, letter)

20

Diğer kullanıcıların belirttiği gibi, enumeratebir yinelenebilir her öğenin yanına artımlı bir dizin ekleyen bir jeneratör.

Bir liste söz sahibi, yani l = ["test_1", "test_2", "test_3"], list(enumerate(l))size böyle bir şey verecektir: [(0, 'test_1'), (1, 'test_2'), (2, 'test_3')].

Şimdi, bu ne zaman yararlıdır? Olası bir kullanım durumu, öğeler üzerinde yineleme yapmak istediğinizde ve yalnızca dizininde bildiğiniz belirli bir öğeyi atlamak istediğinizde, değerini değil (değer o anda bilinmediği için).

for index, value in enumerate(joint_values):
   if index == 3:
       continue

   # Do something with the other `value`

Bu nedenle kodunuz daha iyi okunur, çünkü aynı zamanda döngü için bir düzenli de yapabilirsiniz, rangeancak daha sonra bunları dizine eklemeniz gereken öğelere erişmek için (örn joint_values[i].).

Başka bir kullanıcı kullanımın bir uygulamasından bahsetse de, enumeratekullanmadan zipdaha saf (ama biraz daha karmaşık) bir yol olduğunu düşünüyorum itertools:

def enumerate(l, start=0):
    return zip(range(start, len(l) + start), l)

Misal:

l = ["test_1", "test_2", "test_3"]
enumerate(l)
enumerate(l, 10)

Çıktı:

[(0, 'test_1'), (1, 'test_2'), (2, 'test_3')]

[(10, 'test_1'), (11, 'test_2'), (12, 'test_3')]

Yorumlarda belirtildiği gibi, menzil ile bu yaklaşım, orijinal enumeratefonksiyonun yaptığı gibi rastgele tekrarlanabilirlerle çalışmaz.


Diğer cevap bahseder nedeni itertoolssizin olmasıdır rangeyaklaşım sadece konteynerlerin ile çalışır. enumeratekeyfi yinelenebilirlerle çalışır; bir dosyayı yinelemek istiyorsanız for lineno, line in enumerate(myfile):çalışır, ancak yapamazsınız range(len(myfile))çünkü EOF'a ulaşana kadar uzunluk bilinmiyor.
ShadowRanger

12

Numaralandırma işlevi aşağıdaki gibi çalışır:

doc = """I like movie. But I don't like the cast. The story is very nice"""
doc1 = doc.split('.')
for i in enumerate(doc1):
     print(i)

Çıktı

(0, 'I like movie')
(1, " But I don't like the cast")
(2, ' The story is very nice')
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.