【從C#走進Python】二、迭代器

来源:https://www.cnblogs.com/carmen-019/archive/2020/07/05/13252148.html
-Advertisement-
Play Games

C#與python的迭代器比較: 迭代器 C# Python 一個對象可迭代,需要實現IEnumerable(表示對象可數),IEnumerable就是要實現一個IEnumerator(迭代對象)。 這樣的說法曾經一度讓我很迷,如果返回一個已實現的類似於數組array、列表list類型的IEnume ...


  C#與python的迭代器比較:

迭代器

C#

Python

一個對象可迭代,需要實現IEnumerable(表示對象可數),IEnumerable就是要實現一個IEnumerator(迭代對象)。

 

這樣的說法曾經一度讓我很迷,如果返回一個已實現的類似於數組array、列表list類型的IEnumerator,那實現介面IEnumerable不就很雞肋了?

學習一個新語言,就會重新認識一些語言特性,這個過程是很有趣的。

 

Python的迭代器叫Iterator,可迭代就要實現迭代器__iter__(self),和下一項內容__next__(self),這個設計上,顆粒感更強一些。

IEnumerator GetEnumerator();

__iter__

__next__

註:

1.可以將__iter__和__next__調用替換為python內置函數iter()和next()

2.在python2中實現的方法名是next,為了相容性,python3中要同時實現next(self)

    public class TestGenerable : IEnumerable
    {
        private int n;
        private int a;
        private int b;

        public TestGenerable(int n)
        {
            this.n = n;
            this.a = 1;
            this.b = 1;
        }

        public IEnumerator GetEnumerator()
        {
            for (int i = 0; i < n; i++)
            {
                yield return a;
                int t = a;
                a = b;
                b = t + b;
            }
        }
    }

foreach (var value in new TestGenerable(10))
{ 
    WriteLine(value.ToString());
}
>>> def fbnq(n):
...     a, b = 1,1
...     while n > 0:
...         yield a
...         a, b = b, a+1
...         n -= 1
...
>>> fbnq(1)
<generator object fbnq at 0x0000000002D58E08>
>>> list(fbnq(3))
[1, 1, 2]

 

狹隘的我竟然從來沒有想一想斐波那契數列更好的實現方式,可以說非常沒有靈魂了。

這個實例非常好的說明瞭yield return 怎麼使用,Generator是個什麼東西。

 

Tips:

1.Python沒有for(int i; i <n; i++)這樣的迴圈,python風格是使用range(n),像這樣:

for i in range(5):
    pass..

2.generator是可以傳遞的,

iterator = (‘hello’ for i in rang(3))

註意,加了最外邊的圓括弧就是生成器對象了,當然,最好避免嵌套兩層以上的生成器表達式。

  補充:

Python的迭代器

熱身:

>>> class RepeaterIterator:
...     def __init__(self,source):
...         self.source = source
...     def __next__(self):
...         return self.source
...
>>> repeater = tt('Hello')
>>> next(repeater)
'Hello'

使用next(variable)函數,

解釋器會調用variable實現的__next__函數,

所以會有執行內容。

然而:

>>> for i in repeater:
...     print(str(i))
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'RepeaterIterator' object is not iterable

for in迴圈中,解釋器會找in後面對象實現的__iter__,

沒有實現解釋器會認為其不可迭代,於是報錯;

可以補充一下:

class Repeater:
...     def __init__(self, value1):
...         self.value1 = value1
...     def __iter__(self):
...         return RepeaterIterator(self)
...

>>> class RepeaterIterator:
...     def __init__(self,source):
...         self.source = source
...     def __next__(self):
...         return self.source.value1
...

>>> test = Repeater('hello')
>>> a = 1
>>> for i in test:
...     if a < 5:
...         print(str(i))
...         a += 1
...     else:
...         break
...
hello
hello
hello
hello

上例看著還是挺“複雜”的,

其實iter和next可以寫在同一個類裡面:

class Repeater:
...     def __init__(self, value1):
...         self.value1 = value1
...     def __iter__(self):
...         return self
...     def __next__(self):
...         return self.value

配合語法糖yield服用:

>>> def repeater(value):
...     while True:
...         yield value
>>> a = repeater('hi')
>>> a
<generator object repeater at 0x0000000002DC1E60>

只要使用了yield來返回項的,解釋器認為這是個generator類型;

它和iterator差不多,只不是概念上的區別。

generator是“生成器”,

它的下一項更趨向於經過了複雜的計算處理而出來,

而iterator更“輕”一些。

 

序列過濾(查詢)

C#

Python

LINQ

(本質是使用lambda表達式)

list切片

lambda

生成器表達式

懶得寫

切片:

精髓就一句:

>>> lst = [1,2,3,4,5]
>>> lst[-2::-1]
[4, 3, 2, 1]
>>> lst[-2::-2]
[4, 2]

list是個序列,a:b:c,

a表示第幾個開始,加-號表示倒數數起;

c表示取數跨度,加了-號表示序列反向。

 

切片,目前我體驗來說,

僅 lst[-1] 表示“取最後一項”是香的;

有些硬用切片進行數據篩選,比較非人哉:

dataSet[nonzero(dataSet[:,feature] > value)[0],:]

(康康這啥玩意 %#@$%#@$%4@!!)

要從最裡面的方括弧開始看,[:,feature]取所有行的下標為feature的列(輸出n行1列的數組),如果數組元素大於value,對應位置為true否則為false;

Nonzero結果第一行是入參非0元素的行位置(python的0等價false,1等價true)

最後取dataset中feature列上值大於value的所有行。

 

用對象,用lambda就不香了?

lambda和內置函數filter一起用,就比較LINQ思想了,

下例,以取第4列大於3的所有行:

>>> c
array([[1, 2, 3, 5, 0],
       [0, 1, 2, 1, 1]])
>>> list(filter(lambda line:line[3]>3, c[:,:]))
[array([1, 2, 3, 5, 0])]

如果需要轉換為numpy.array類型,可以這樣處理:

>>> np.array(list(ex))

生成器表達式,格式:

genexpr = (expression for item in collection if condition)

[註意,最外一定要有圓括弧]

[expression是item輸出處理]

>>> c
array([[1, 2, 3, 5, 0],
       [0, 1, 2, 1, 1]])
>>> ex = (line for line in c[:,:] if line[3] > 3)
>>> for i in ex:
...     print(i)
...
[1 2 3 5 0]

如果需要轉換為numpy.array類型,可以這樣處理

>>> np.array(list(ex))

註:generator是單向不可逆的,next()後就釋放當前項了。

疑問:C#linq靈魂的鏈式方法(拓展方法),在python是怎麼表現的呢

 

  python的變數適用範圍,python的裝飾器,此類都是大區別與C#的,下集整理。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • First. 什麼是 algolia search? 根據algolia官方網站自我闡述:Algolia是一個托管搜索引擎,提供全文,數字和多面搜索,能夠從第一次擊鍵中提供實時結果。 Algolia強大的API可讓您快速無縫地在網站和移動應用程式中實施搜索。我們的搜索API每月為成千上萬的公司提供數 ...
  • 在“JavaScript圖形實例:SierPinski三角形” 和“JavaScript圖形實例:Levy曲線及其變形”等文章中我們介紹了通過遞歸生成分形圖形的方法。我們可以將繪製的分形圖形每隔一定的時間間隔後,增加遞歸深度重新繪製一次,這樣就可以得到分形圖形的動態生成效果。 1.SierPinsk ...
  • Nuxt 是 Vue 項目伺服器端渲染(SSR)解決方案。而在使用時,就會遇到前後端分離情況下的功能變數名稱或埠不一致導致的跨域問題。本文將介紹如何通過設置代理解決 Nuxt 與 axios 集成的跨域問題。 ...
  • Electron是一個可以使用 JavaScript,HTML 和 CSS 構建跨平臺桌面應用程式的開源框架。 本文主要分享一下採用vue + electron開發桌面程式的搭建過程。 1. 環境準備 這裡採用的是vue-cli3.x,可以通過下麵的指令查看當前vue-cli的版本: vue --v ...
  • #讀後感# 《企業IT架構轉型之道-阿裡巴巴中台戰略思想與架構實戰》鐘華(花名:古謙)編著,阿裡巴巴中間件首席架構師,15年中間件領域行業經驗。 進入新公司第一天,領導就給了這本書,慚愧,剛看完... 一本推動“中台建設”指導性實戰用書,濃縮了10來年的經驗,從架構層面詳細敘述阿裡共用業務事業部:技 ...
  • 抽象工廠模式 優化抽象工廠 非同步工廠 在學習抽象工廠模式前,先來回顧一下前面的簡單工廠和工廠方法模式。簡單工廠的職責非常簡單:構造某個實體類型,然後把實例作為抽象類型返回; 工廠方法模式則進一步抽象出一個抽象的創建者和一個抽象的產品類型,而實際的執行過程是具體工廠創建具體的產品類型,具體工廠和具體產 ...
  • 我的LeetCode:https://leetcode-cn.com/u/ituring/ 我的LeetCode刷題源碼[GitHub]:https://github.com/izhoujie/Algorithmcii LeetCode 題目 字元串有三種編輯操作:插入一個字元、刪除一個字元或者替換 ...
  • 問題來源: 在寫二叉樹序列化與反序列化時發現序列化函數為char* Serialize1(TreeNode *root) 其函數返回類型為char*,但是我在實現的過程中為了更方便的操作添加字元串使用的是C++中string類型的變數,這就導致我最後得到的結果res是string類型,若是要返回需要 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...