簡體   English   中英

為什么Python將元組,列表,集合和字典視為根本不同的東西?

[英]Why does Python treat tuples, lists, sets and dictionaries as fundamentally different things?

我喜歡Python的原因之一是由元組,列表,集合和字典提供的表達能力/減少編程工作。 一旦你理解了列表理解和一些使用infor的基本模式,生活就會變得更好! Python搖滾。

但是我確實想知道為什么這些結構會被視為不同,以及隨着時間的推移它會如何變化(變得陌生)。 回到Python 2.x,我可以提出一個論點,他們都只是基本集合類型的變體,並且有些令人惱火的是,一些非奇特的用例要求你將字典轉換為列表並返回再次。 (字典不僅僅是具有特定唯一性約束的元組列表嗎?列表不是僅具有不同類型的唯一性約束的集合嗎?)。

現在在3.x世界中,它變得更加復雜。 現在有名為元組 - 開始感覺更像是一個特例字典。 現在有訂單的詞典 - 開始感覺更像是一個列表。 我剛看到有序套裝的配方。 我可以想象一下這個......還有什么獨特的清單等等。

Python的禪宗說“應該有一個 - 最好只有一個 - 明顯的方式”。 在我看來,這種專門的集合類型的大量與這個Python規則相沖突。

硬核Pythonistas的想法是什么?

這些數據類型都有不同的用途,在理想的世界中,您可以更多地統一它們。 但是,在現實世界中,我們需要有效地實現基本集合,例如,排序會增加運行時懲罰。

命名元組主要用於使stat()等接口更有用,並且在處理SQL行集時也可以很好用。

你正在尋找的大統一實際上是以不同的訪問協議(getitem,getattr,iter,...)的形式,這些類型混合和匹配用於它們的預期目的。

tl; dr(鴨子打字)

你在所有這些數據結構中看到一些相似之處是正確的。 請記住,python使用duck-typing (如果它看起來像鴨子和呱呱叫鴨子那么它就是鴨子)。 如果您可以在相同的情況下使用兩個對象,那么對於您當前的意圖和目的,它們可能也是相同的數據類型。 但是你總是要記住,如果你試圖在其他情況下使用它們,它們可能不再以相同的方式運行。

考慮到這一點,我們應該看看你提到的四種數據類型的實際不同和相同之處,以便大致了解它們可以互換的情況。

可變性(你可以改變嗎?)

您可以更改詞典,列表和集。 如果不制作副本,則無法“更改”元組。

  • 可變: dictlistset

    永恆: tuple

Python string也是一種不可變類型。 為什么我們想要一些不可變對象? 我會從這個答案中解釋一下:

  1. 不可變對象可以進行很多優化

  2. 在Python中,只有不可變的是可散列的(並且只有可散列的對象可以是集合的成員,或者是字典中的鍵)。

比較此屬性,列表和元組看起來像“最接近”的兩種數據類型。 在高級別,元組是列表的不可變“凍結幀”版本。 這使得列表對於隨時間變化的數據集很有用(因為您不必復制列表來修改它),但是元組對於字典鍵(必須是不可變類型)這樣的東西很有用。

訂購(以及關於抽象數據類型的說明)

字典就像一個集合,沒有固有的概念順序。 這與有訂單的列表和元組形成對比。 dict或set中的項目的順序是從程序員中抽象出來的,這意味着如果元素A for k in mydata循環中的for k in mydata出現在B之前,則不應該(並且通常不能)依賴於A之前的A B一旦你開始改變mydata

  • 保留訂單: listtuple

    非訂單保留: dictset

從技術上講,如果你連續兩次迭代mydata它將是相同的順序,但這是python機制的一個方便的特性,而不是set 抽象數據類型的一部分( 數據的數學定義)類型)。 列表和元組確實保證了順序,特別是不可變的元組。

你在迭代時看到的東西(如果它像鴨子一樣走路......)

  • 每個“元素”一個“項目”: setlisttuple

    每個“元素”有兩個“項目”: dict

我想在這里你可以看到一個命名元組,它具有每個元素的名稱和值,作為字典的不可變模擬。 但這是一個微妙的比較 - 請記住,如果您嘗試在命名元組上使用僅字典方法,則鴨子類型將導致問題,反之亦然。

直接回答您的問題

字典不僅僅是具有特定唯一性約束的元組列表嗎?

不,有幾個不同之處。 字典沒有固有的順序,這與列表不同。

此外,字典具有每個“元素”的鍵和值。 另一方面,元組可以具有任意數量的元素,但每個元素僅具有值。

由於字典的機制,鍵的作用就像一個集合,如果你有密鑰,你可以在恆定的時間內查找值。 在元組列表(這里是對)中,您需要遍歷列表直到找到密鑰,這意味着搜索將與列表中的元素數量成線性關系。

但最重要的是,字典項可以更改,而元組則不能。

列表不是僅具有不同類型的唯一性約束的集合嗎?

我再次強調,集合沒有固有的順序,而列表則沒有。 這使列表更有用於表示堆棧和隊列之類的內容,您希望能夠記住附加項目的順序。 套裝沒有這樣的保證。 然而,它們確實提供了能夠在恆定時間內進行成員資格查找的優勢,而再次列表需要線性時間。

現在有名為元組 - 開始感覺更像是一個特例字典。 現在有訂單的詞典 - 開始感覺更像是一個列表。 我剛看到有序套裝的配方。 我可以想象一下這個......還有什么獨特的清單等等。

在某種程度上,我同意你的意見。 但是,數據結構庫可用於支持已經完善的數據結構的常見用例。 這使程序員不必浪費時間嘗試為標准結構提供自定義擴展。 只要它不會失控,我們仍然可以看到每個解決方案中的獨特用途,最好在貨架上安裝一個輪子,這樣我們就不需要重新發明它了。

一個很好的例子是Counter()類。 這個專業詞典對我來說比我可以使用的次數多了很多次(badoom-tshhhhh!),它為我節省了編寫自定義解決方案的工作量。 我寧願有一個解決方案,社區正在幫助我開發和保持適當的python最佳實踐,而不是在我的自定義數據結構文件夾中的東西,並且每年只使用一次或兩次。

首先,在Python 2中引入了有序字典和命名元組,但這不是重點。

我不會指出你的文檔,因為如果你真的感興趣,你會讀它們。

集合類型之間的第一個區別是可變性。 tuplefrozenset是不可變類型。 這意味着它們比listset更有效。

如果你想要隨機或按順序訪問的東西,但最終會改變,你需要一個list 如果你想要的東西也可以在開始時改變,你需要一個deque

你根本無法擁有自己的蛋糕而且吃得太多 - 你添加的每個功能都會讓你失去一些速度。

dictsetlists和元set有根本的不同。 它們存儲密鑰的哈希值,允許您快速查看項目是否在其中,但需要密鑰可以清除。 您沒有使用鏈接列表或數組獲得相同的成員資格測試速度。

當你到達OrderedDictNamedTuple ,你談論的是用Python實現的內置類型的子類,而不是C語言。它們用於特殊情況,就像你必須導入的標准庫中的任何其他代碼一樣。 它們不會使命名空間變得混亂,但是當你需要它們時很高興。

有一天,你會編碼,你會說,“男人,現在我確切地知道他們的意思是'應該有一個 - 最好只有一個 - 明顯的方式去做', set 正是我需要什么,這一點,我很高興它是Python語言的一部分!如果讓我用一個列表,它會永遠需要“。 那時你會明白為什么存在這些不同的類型。

字典按鍵索引(事實上,它是一個哈希映射); 一個通用的元組列表將不會。 您可能會認為兩者都應該作為關系實現,並且能夠隨意添加索引,但實際上,為常見用例提供優化類型更方便,更有效。

新的專業集合被添加,因為它們很常見,很多人最終會使用更基本的數據類型來實現它們,然后你就會遇到輪子改造的常見問題(浪費精力,缺乏互操作性......)。 如果Python只提供了一個完全通用的構造,那么我們會讓很多人問“如何使用關系實現集合”等。

(順便說一句,我在數學或數據庫意義上使用關系)

所有這些專門的集合類型都提供了由list,tuple,dict和set的“標准”數據類型無法充分或有效提供的特定功能。

例如,有時您需要一組唯一項,並且還需要保留遇到它們的順序。 您可以使用集合來跟蹤成員資格和列表以跟蹤順序,但是您的解決方案可能比專門為此目的而設計的專用數據結構(例如有序集)更慢且更需要內存。

這些其他數據類型(您將其視為基本數據類型的組合或變體)實際上填補了基本數據類型留下的功能空白。 從實際角度來看,如果Python的核心或標准庫沒有提供這些數據類型,那么任何需要它們的人都會發明自己的低效版本。 它們的使用頻率低於基本類型,但通常足以使其提供標准實現。

我最喜歡Python中的一件事就是敏捷性。 許多功能,有效和可用的集合類型給了我。

還有一種方法可以做到這一點 - 每種類型都有自己的工作。

數據結構的世界(語言不可知)通常可以歸結為一些小的基本結構 - 列表,樹,散列表和圖形等,以及它們的變體和組合。 每個在使用和實施方面都有自己的特定目的。

我不認為您可以執行諸如將字典縮減為具有特定唯一性約束的元組列表而不實際指定字典的操作。 字典具有特定目的 - 鍵/值查找 - 並且數據結構的實現通常是針對這些需求而定制的。 集合在很多方面都像字典,但集合上的某些操作在字典(union,disjunction等)上沒有意義。

我沒有看到這違反了“禪宗之謎”的做法。 雖然您可以使用排序字典來執行字典所執行的操作而不使用已排序的部分,但您更多地違反了Occam的剃刀並且可能會導致性能下降。 我認為這不同於能夠在語法上以不同的方式做一些Perl。

Python的禪宗說“應該有一個 - 最好只有一個 - 明顯的方式”。 在我看來,這種專門的集合類型的大量與這個Python規則相沖突。

不是遠程的。 這里有幾件不同的事情要做。 我們為工作選擇合適的工具。 所有這些容器都是根據幾十年前經過考驗,測試和真實的CS概念建模的。

字典與元組不同:它們針對鍵值查找進行了優化。 元組也是不可變的,它將它與列表區分開來(您可以將其視為類似於frozenlist )。 如果您發現自己將字典轉換為列表並返回,那么您幾乎肯定會做錯事; 一個例子會有所幫助。

為方便起見,存在命名元組,實際上是用於替換簡單類而不是字典。 有序詞典只是為了記住事物被添加到字典中的順序。 並且在3.x中都不是新的(雖然可能有更好的語言支持他們;我沒看過)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM