Python yineleyici ve C ++ yineleyici arasındaki en büyük fark ...

Yazar | Ying Yu Lou

Sorumlu Editör | Hu Weiwei

Önsöz

Yineleyici, Python'da ve diğer çeşitli programlama dillerinde çok yaygın ve önemli bir kavramdır, ancak gizemle doludur. İster Python'un temel yerleşik işlevleri isterse çeşitli gelişmiş konular olsun, yineleyiciler her yerde görülebilir.

Peki yineleyici kavramı nedir? Neden çeşitli programlama dillerinde yaygın olarak kullanılmaktadır? Bu makale, bu sorun serisini C ++ ve Python'a dayalı olarak derinlemesine tartışacaktır.

Yineleyici nedir? Neden yineleyiciler kullanmalıyız?

Yineleyici nedir? Python'u ilk öğrendiğimde, yineleyicileri "xxx içinde ..." için "..." konumuna yerleştirilebilecek bir şey olarak anladım; daha sonra, daha derinlemesine öğrendikçe, yinelemelerin yinelemeyi uygulamanın bir yolu olduğunu öğrendim Protokolün amacı; C ++ 'ı öğrenirken, bir yineleyicinin bir işaretçi gibi davranan bir nesne olduğunu öğrendim ...

Aslında, bir yineleyici, Yineleyici Modeline eşlik eden soyut bir kavramdır. Amacı, farklı veri yapılarının verilere erişme yollarını ayırmak ve birleştirmektir, böylece veri yapısına erişmesi gereken çeşitli işlevler Farklı veri yapıları aynı arayüzü sürdürebilir.

Python yineleyicileri tartışan birçok kitap ve makalede, iki görüş gördüm: 1. Yineleyici, veri yapısı tarafından oluşturulan belleği kaydetmektir; 2. Geçiş yineleyici daha verimlidir.

Bu iki argüman çok yanlıştır: Birincisi, veri yapısında tanımlanmayan bazı yineleyiciler dışında (dosya tanıtıcıları, itertools modülünde sayım ve döngü gibi sonsuz yineleyiciler vb.), Diğer yineleyiciler belirli Veri yapısı açısından, bellek kaydetmenin bir avantajı yoktur; ikinci olarak, yineleyici oldukça genelleştirilmiş bir uygulama olduğundan, yineleyici her hareket ettiğinde fazladan iş yapması gerekir (örneğin, Python'un yineleyicinin tüketip tüketmediğini sürekli olarak kontrol etmesi gerekir. C ++ kod çözme kabının, yığın üzerinde depolama için kullanılan çoklu süreksiz belleğe bağlanması gerekir.), Bu nedenle yineleyiciyi çaprazlama verimliliği, kabı doğrudan çaprazlama işlemine yakın veya daha düşük olmalıdır, ancak çok da olmamalıdır. Doğrudan orijinal kabı geçmekten daha yüksek olabilir.

Özetle, yineleyicilerin varlığının anlamı, zamanla yer değiş tokuşu değil, uzay değiş tokuşu için zaman değil, bir tür bağdaştırıcıdır. Yineleyicilerin varlığı, aynı ifadeyi çeşitli kapsayıcılarda gezinmek için kullanmamıza veya C ++ algoritma modülünde gösterildiği gibi çeşitli kapsayıcıları işlemek için aynı arabirimi kullanmamıza izin verir.

Bu kapsayıcılar bir dizi veya bitişik bellek listesi veya bitişik belleğin birden çok bölümünün bir dekontu veya hatta bağlantılı bir liste veya tamamen süreksiz belleğin karma tablosu olabilir. Buna hiç ihtiyacımız yok. Dikkat Yineleyici, farklı kapsayıcılar için verileri nasıl alır?

C ++ 'da yineleyiciler

3.1 Genelleme işaretçisi

C ++ 'da, yineleyiciler Genelleştirilmiş İşaretçiler biçiminde sunulur. Genelleştirilmiş işaretçi tanımı, aşağıdaki iki durumu içeren functor tanımına benzer:

  • Gerçek bir işaretçi

  • İşaretçi değil, ancak bazı işaretçi operatörleri aşırı yüklendi ("*, ++, -,! =" Vb. Gibi), davranışını işaretçilerle benzer hale getiriyor

  • Gerçek bir işaretçi olarak "gizlemek" için genelleştirilmiş bir işaretçinin aşırı yüklediği operatörlerin sayısına göre, yineleyiciler aşağıda gösterildiği gibi beş türe ayrılır.

    3.2 C ++ Yineleyicilerin Sınıflandırılması

    C ++ yineleyiciler, destekledikleri davranışlara göre beş kategoriye ayrılır:

  • Giriş Yineleyici: Bir değer olarak değil, yalnızca bir r değeri olarak kullanılabilir. Karşılaştırılabilir ("== ve! =")

  • Çıktı Yineleyici: Yalnızca bir l değeri olarak kullanılabilir, bir r değeri olarak kullanılamaz

  • Forward Iterator (Forward Iterator): tüm giriş yineleyici işlemlerinin yanı sıra tek adımlı ileri işlemleri (++) destekler

  • Çift Yönlü Yineleyici: tüm ileri yineleme işlemlerinin yanı sıra tek adımlı geriye doğru işlemleri (-) destekler

  • Rastgele Erişim Yineleyici (Random Access Iterator): tüm çift yönlü yineleme işlemlerini ve tek adımlı olmayan çift yönlü hareket işlemlerini destekler

  • İleri yineleyiciler, çift yönlü yineleyiciler ve rastgele erişim yineleyiciler için, temelde yatan sabit (Düşük Düzey Sabit) kısıtlaması yoksa, tüm çıktı yineleyici işlemleri de desteklenir.

    3.3 Yineleyici adaptörü

    Ayrıca, C ++ 'da, bazı yineleyici olmayan nesnelerin yineleyiciler gibi davranmasını sağlamak veya yineleyicilerin bazı varsayılan davranışlarını değiştirmek için kullanılan, kabaca aşağıdaki kategorileri içeren bir dizi yineleyici bağdaştırıcısı vardır:

  • eklemek Yineleyici (Yineleyici Ekle): Yazma işlemini kabın içine yineleyicinin sol değerinde yapın eklemek Veri işlemi, basın eklemek Konum farklıdır, front_insert_iterator, back_insert_iterator ve insert_iterator olarak bölünebilir

  • Reverse Iterator: Yineleyicinin hareket yönünü tersine çevirin. "+" İşleminin sola, "-" işleminin sağa hareket etmesini sağlar (Python'un tersine çevrilmiş işlevine benzer)

  • Yineleyiciyi Taşı: Yineleyicinin değerini bir Rvalue Referansı haline getirin (Rvalue Reference)

  • Akış Yineleyici: Akış nesnelerinin davranışını yineleyicilere uyarlayın (Python dosya tanıtıcılarına benzer)

  • Python'da yineleyiciler

    4.1 Yineleyici Protokolü

    Python'da yineleyiciler, Duck Type altındaki Yineleyici Protokolüne göre uygulanır. Yineleyici protokolü şunu şart koşar: Bir sınıf yinelenebilir bir nesne (Yinelenebilir Nesne) olmak istiyorsa, __iter__ yöntemini uygulamalı ve dönüş değeri __next__ yöntemini uygulayan bir nesne olmalıdır.

    Yani __iter__ yöntemini uygulayan sınıf yinelenebilir bir nesne haline gelir ve __next__ yöntemini uygulayan sınıf bir yineleyici olur.

    Açıkçası, __iter__ yöntemi, iter işlevine karşılık gelen sihirli yöntemdir ve __next__ yöntemi, sonraki işleve karşılık gelen sihirli yöntemdir.

    Yinelenebilir bir nesne için, "__next__ yöntemini kim uyguluyor?" Sorusunu tartışmak için, yinelenebilir nesnelerin gerçekleştirilmesi iki duruma ayrılabilir:

  • self __next__ uygulamaz: __iter__ yönteminin dönüş değeri bir Yineleyici ise, self yinelenebilir bir nesnedir. Bu noktada, self yinelemeli işlemi başka bir veri yapısına "yetkilendirir". Örnek kod aşağıdaki gibidir:

  • class SampleIterator:

    def __iter __ (kendisi):

    dönüş iter (...)

  • self __next__ 'yi uygular: __iter__ yöntemi self' i döndürürse, kendinin bir yineleyici olarak kullanılacağı anlamına gelir. Şu anda, tam bir yineleyici protokolü elde etmek için self'in __next__ yöntemini uygulamaya devam etmesi gerekir. Örnek kod aşağıdaki gibidir:

  • class SampleIterator:

    def __iter __ (kendisi):

    kendine dön

    def __sonraki __ (kendi):

    # Son değil

    Eğer ...:

    dönüş ...

    # Sona Ulaş

    Başka:

    StopIteration'ı yükselt

    Bu örnekte yineleyici sonlandırıldığında Python yineleyicinin bir StopIteration istisnası atarak tükendiğini görebiliriz.

    4.2 Jeneratör

    Generator, Python'a özgü bir dizi özel gramerdir. Asıl amacı, sınıflar yerine fonksiyonlara dayalı bir yineleyici tanımlama yöntemi sağlamaktır. Aynı zamanda Python, kapsamlı sözdizimine dayalı yineleyicileri hızla oluşturan oluşturucu anlayışlara da sahiptir. Üreteçler genellikle basit mantık yineleyicilerinin oluşturulması gereken durumlar için uygundur.

    Getiri anahtar sözcüğü bir işlevin tanımında göründüğü sürece, işlev artık bir işlev olmayacak, ancak bir "oluşturucu oluşturucu" haline gelecektir. Bu kurucuyu çağırmak bir üreteç nesnesi oluşturabilir.

    Buradan anlaşılacağı gibi, sadece gramerin kendisini tartışırsak ve uygulamayı umursamazsak: oluşturucu sadece fonksiyon tarafından tanımlanan grameri "ödünç alır" ve fonksiyonla hiçbir ilgisi yoktur (bu, jeneratörün temel uygulamasının da fonksiyondan bağımsız olduğu anlamına gelmez) . Örnek kod aşağıdaki gibidir:

    def SampleGenerator:

    Yol ver ...

    Yol ver ...

    Yol ver ...

    Oluşturucu anlayışı daha da basittir, listeyi anlamanın parantezlerini parantez olarak değiştirin:

    (... içinde ... içinde ...)

    Özetle, üreteçler Python'a özgü yineleyiciler oluşturmanın özel bir yoludur. Jeneratör oluşturulduktan sonra, tüm yineleme protokolünü otomatik olarak uygulayacaktır.

    4.3 Sonsuz Yineleyici

    İtertools modülünde üç özel Sonsuz Yineleyici uygulanır: aralıkları ifade eden sıradan yineleyicilerden farklı olan sayma, döngü ve yineleme. Sonsuz bir yineleyicide yineleme sonsuz bir döngü ile sonuçlanacaksa, sonsuz bir yineleyici genellikle yalnızca bir sonraki işlev kullanılarak elde edilebilir.

    4.4 C ++ Yineleyici ile Karşılaştırma

    Yukarıdaki tartışmada, Python'un yalnızca bir tür yineleyici olduğu bulunabilir.Bu tür yineleyici, yalnızca tek yönlü, tek adımlı ileri işlemleri gerçekleştirebilir ve bir ldeğer olarak kullanılamaz. Bu nedenle, Python'un yineleyicisi, çok düşük seviyeli bir yineleyici olan C ++ 'da tek yönlü bir salt okunur yineleyici olmalıdır.

    Buna ek olarak, yineleyici yalnızca tek yönlü hareketi desteklediğinden, ileri doğru hareket ettikten sonra geri döndürülemez.Eğer bitmiş bir yineleyicinin üzerinden geçerse, for döngüsü herhangi bir hata olmadan doğrudan çıkar. Bu davranış genellikle bazı zorluklarla sonuçlanır. Lütfen gerçek kullanımda tespit edilen hatalara dikkat edin.

    Özetle, Python'un yineleyiciler uygulaması aslında oldukça eksiktir ve dikkatli kullanılmalıdır.

    Yineleyici geçerliliği

    5.1 Yineleyicilerin geçerliliği nedir?

    Yineleyicinin kendisi bağımsız bir veri yapısı olmadığından, işaretçi tarafından gösterilen bellek değiştiğinde sıradan işaretçiler gibi diğer veri yapılarındaki değerlere işaret eden genelleştirilmiş bir işaretçi olduğundan, yineleyici de başarısız olacaktır.

    Yineleyici tarafından işaret edilen veri yapısı salt okunur ise, açıktır ki, yıkıcı çağrılana kadar yineleyici geçersiz olmayacaktır. Ancak yineleyici tarafından işaret edilen veri yapısı mevcutken ortaya çıkarsa eklemek Veya silme işlemi, yineleyici geçersiz hale gelebilir. Bu nedenle, belirli bir işlemin yineleyicinin konteynere başarısız olmasına neden olup olmayacağını tartışmak çok önemli bir konudur.

    5.2 C ++ Yineleyicilerin Etkinliği

    Python'da list ve deque gibi veri yapılarının C ++ uygulaması olmadığından, bu makalede yineleyicilerin vektör ve unordered_map'in iki veri yapısı için etkinliği kısaca tartışılmaktadır.

    Vektör için, bellek genişletme ve aktarım işlemleri nedeniyle, potansiyel olarak bellek genişlemesine neden olacak herhangi bir yöntem, geri itme, geri yerleştirme, ekleme, yerleştirme vb. Dahil olmak üzere yineleyiciye zarar verecektir.

    Unordered_map'in durumu vektörün durumuna benzer. eklemek İşlem aynı zamanda yineleyiciye de zarar verecektir.

    5.3 Python Yineleyicilerinin Etkinliği

    Not: Bu bölümde tartışılan tüm içerik, tahmin ve çıkarım yapmak için gerçek davranışa dayanmaktadır.Python kaynak kodunda araştırılmamış ve doğrulanmamıştır ve yalnızca okuyucuların referansı içindir.

    5.3.1 Kuyruk eklemek İşlem, mevcut öğeye işaret eden Liste yineleyicisine zarar vermez

    Aşağıdaki kodu göz önünde bulundurun:

    numList =

    numListIter = iter (numList)

    sonraki (numListIter)

    aralıktaki i için (1000000):

    numList.append (i)

    # print 2

    baskı (sonraki (numListIter))

    C ++ 'da bir vektör üzerinde çok fazla geri itme gerçekleştirirseniz, ikinci elemanın yineleyicisinin süresi dolmuş olmalıdır. Ancak Python'da görebileceğiniz gibi, Listenin yineleyicisi geçersiz değildir ve yine de 2 döndürür.

    Bu nedenle, tahmin edilebilir: Python, List öğelerine işaretçileri değil, yalnızca kabın dizin değerini izler.

    5.3.2 Kuyruk eklemek İşlem, liste kuyruğu yineleyicisine zarar verecek

    numList =

    numListIter = iter (numList)

    # 1

    sonraki (numList)

    numList.append (3)

    # 2

    sonraki (numListIter)

    # 3

    baskı (sonraki (numListIter))

    İlk olarak, Python'da kuyruk yineleyiciler kavramı yoktur. Ancak yukarıdaki koddan, yineleyici tarafından işaret edilen Liste uzadığında, yineleyicinin bitiş noktasının da değiştiği, yani orijinal kuyruk yineleyicinin artık uygulanamayacağı görülebilir.

    Bu davranış, "yineleyiciler yalnızca öğe indeksi değerlerini izler" çıkarımıyla da açıklanabilir.

    5.3.3 Yineleyici tükendiğinde kalıcı olarak hasar görecektir

    Aşağıdaki kodu göz önünde bulundurun:

    numList =

    numListIter = iter (numList)

    numListIter içindeki _ için:

    geçmek

    numList.append (3)

    # StopIteration

    baskı (sonraki (numListIter))

    Bir yineleyici için yineleyici tükenecektir.C ++ 'da bu, baş ve kuyruk yineleyicilerinin eşit olmasına neden olur, ancak yukarıdaki koddan, Python yineleyici bittiğinde, kapta devam etse bile artık kullanılamayacağını görebiliriz. Buna eleman eklemek yeterli değil.

    Python'un yineleyicisinde yineleyicinin tükenip bitmediğini gösteren bazı işaretler olduğu görülebilir. Yineleyici bitmiş olarak işaretlendikten sonra asla kullanılamaz.

    5.3.4 Herhangi eklemek İşlemler Dict yineleyicisine zarar verir

    Aşağıdaki kodu göz önünde bulundurun:

    numDict = {1: 2}

    numDictIter = iter (numDict)

    numDict = 4

    # Çalışma hatası

    sonraki (numDictIter)

    Bir Dict yaparken eklemek İşlemden sonra, orijinal Dict yineleyicisi derhal geçersiz kılınır ve bir RuntimeError hatası atılır. Bu, C ++ 'daki davranışla tutarlıdır ve daha güvenlidir.

    Set ve Dict aynı yineleyici başarısızlık özelliğine sahiptir, bu nedenle tartışma tekrarlanmayacaktır.

    postscript

    Yineleyicilerin hikayesi burada bitiyor. Genel olarak, Python'daki yineleyiciler yaygın olarak kullanılsa da, bunlar gelişmiş ve esnek bir uygulama değildir ve bazı kara büyü vardır. Bu nedenle, yalnızca derinlemesine bir anlayış yineleyicilerden gerçekten iyi bir şekilde faydalanabilir. Mutlu programlar ~

    Yazar: bezelye kedisi, 985 üniversite mezunu, hem inekler hem de insan duyguları. Halka açık Python kedisi, Python teknolojisi, veri bilimi ve derin öğrenmeye odaklanır ve ilginç ve yararlı bir öğrenme paylaşım platformu oluşturmaya çalışır.

    Feragatname: Bu makale yazar tarafından gönderilmiş olup, telif hakkı yazara aittir.

    Son

    Herkese CSDN'nin iyi arkadaşlarını tavsiye etmeme izin verin- Program ömrü .

    Neden program ömrü öneriliyor?

    Program ömrü milyonlarca programcıyı bir araya toplar, burada geliştirme anekdotlarına gülebilir ve program ömrü hakkında şikayette bulunabilirsiniz.

    Sektördeki önemli noktalardan deneyim analizine, işyerindeki kafa karışıklığından trendlere ve programcıların sırlarını size sağlayacağız Tek tek Açıklandı.

    Teknik kişilerin yazımı nasıl gerçekleştirilir?
    önceki
    Geliştirici, asıl endişeleriniz neler? | AI ProCon 2019
    Sonraki
    Pinduoduo, Qutoutiao ve Xiaohongshu'nun arkasındaki Şangay İnternet genlerinin sökülmesi
    "TFBOYS" "Paylaş" 190622 Yemek yiyip yememek arasında güçlü bir tezat var, TFBOYS hayranlarına "şarkı söylemeye" kararlı
    2050'de dünya şehirlerinin "hava tahmini": Londra'da ortalama yaz sıcaklığı 27 derece. 2050'de şehirler ne kadar sıcak olabilir?
    "TFBOYS" "Hisse" 190622 Wang Yuan cesurca ileri doğru yürüyor, sırtı sınırsız olasılıklarda sağlam.
    "That Boy in My Family" üç ağda birinci oldu ve arka arkaya dokuz şampiyonluk elde etti. Chen Xuedong'un yerli ailesi çok tartışılıyor
    Orijinal sesi bırakın! OPPO Reno Müzik Festivali'nin orijinal sesi Chongqing gecesini ateşliyor
    Huawei Hongmeng bir IoT işletim sistemidir; ByteDance Feichao, App Store'dan kaldırıldı; FFmpeg yazarı JS motoru yazdı | Geek Başlıkları
    İnternet Polisi Söylentileri Yalanlıyor: Oolong, Wenzhou'daki Ouhai Caddesi'nde Çocuk Hırsızlığına Dair Net Söylenti
    Şangay'daki çöp sınıflandırmasının yeni kilometre taşı olan 1 Temmuz'da, önce Japonya'daki çöp sınıflandırmasını ve arıtmayı dinleyelim
    Geliştiricilerin başarılı bir şekilde ilerlemesine yardımcı olan, HUAWEI CLOUD'dan çok yönlü bir geliştirici konferansı
    Pekin "HD Güzellik Modu" nu açar, Yaz Sarayı berrak su ve mavi gökyüzü ile pitoresktir
    Yüz tanıma hardcore popüler bilim: kalabalığın içinde kendine bak, yüzünü asla unutma
    To Top