【從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
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...