2010-09-14 31 views
6

集合和列表在Python中的處理方式不同,似乎沒有統一的方式來處理這兩者。例如,使用add方法將項目添加到set,對於list使用append方法完成項目。我意識到這背後有不同的語義,但是那裏也有通用的語義,並且通常有一種算法可以處理一些關於共性的關注,而不是差異。 C++ STL表明這可以工作,爲什麼Python中沒有這樣的概念?爲什麼在Python中不能統一處理集合?

編輯:在C++中我可以使用output_iterator存儲在採集的(幾乎)任意類型,包括列表和集合的值。我可以編寫一個算法,將這樣一個迭代器作爲參數並將元素寫入它。該算法對於支持迭代器的容器(或其他設備,可能是文件)完全不可知。如果支持容器是一個忽略重複的集合,那麼這是調用者的決定。我的具體問題是,它現在已經發生好幾次了,例如我爲某個任務使用了list,後來決定set更合適。現在我必須在我的代碼中的幾個地方將append更改爲add。我只是想知道爲什麼Python對這種情況沒有概念。

+1

「集合和列表在Python中的處理方式不同」,因爲它們本質上**不同。它們不能被製成「統一的」,因爲 - 它們與浮點和文件不同。 「我知道有不同的語義」。好的。你在問什麼?特別?你能否提供你想要的更詳細的例子? – 2010-09-14 10:27:00

+0

@ S.Lott:我添加了一個示例和一些說明。 – 2010-09-14 10:53:11

+0

「一組忽略重複」?什麼?那是什麼?集合 - 按定義 - 不能有重複。我不明白你在問什麼。 – 2010-09-14 13:32:11

回答

6

直接回答:這是一個設計缺陷。

你應該能夠插入任何容器,通用插入是有意義的(例如排除字典)與相同的方法名稱。應該有一個一致的通用名稱來插入,例如。 add,對應於set.addlist.append,所以你可以添加到一個容器,而不必關心你要插入什麼。

在不同類型中對此操作使用不同的名稱是一種不必要的不​​一致性,並且設置了較差的基本標準:庫應該鼓勵用戶容器使用一致的API,而不是爲每個基本容器提供大部分不兼容的API。

也就是說,在這種情況下,這通常不是一個實際問題:大多數情況下,函數的結果是項目列表,將其作爲生成器實現。它們允許處理這兩個一致(從功能的角度看)迭代,以及其他形式:

def foo(): 
    yield 1 
    yield 2 
    yield 3 

s = set(foo()) 
l = list(foo()) 
results1 = [i*2 for i in foo()] 
results2 = (i*2 for i in foo()) 
for r in foo(): 
    print r 
+1

+1生成器。 – 2010-09-14 10:54:55

+0

嗯,Python想要明確,所以只要試着拿出一個動詞,說「保留秩序」(列表)和「不保存秩序」(對於集),在同一時間!相當不可能; -P但正如你所說,實際上有一個統一的方法來構造集合和列表,並且比調用'add'或'append'更加pythonic。 +1。 – 2010-09-14 13:13:32

+0

也許與其說是一種不同的思維方式,不如說是一種設計缺陷。在C++標準庫中,生成值的函數接受輸出迭代器。在Python中,產生值的函數被編譯爲一個生成器。如果您希望Python更像C++標準庫,您可以創建一個OutputIterator類,該類在其構造函數中接受各種容器類型,並計算出在每個容器上調用哪種方法。你可以這樣使用它: my_func(iter,OutputIterator(my_container)) – 2010-09-14 18:00:43

4

加和加的不同。集合是無序的並且包含獨特的元素,而附加提示該項目總是被添加,並且這在最後特別地完成。

集合和列表都可以被視爲可迭代,這是它們的通用語義,並且可以由您的算法自由使用。

如果你有一個算法依賴於某種加法,你不能依賴於集合,元組,列表,字典,行爲相同的字符串。

+1

+1:給一個集合添加''可能沒有任何作用。追加到列表總是有效果的。列表有「擴展」 - 這對於一組意味着什麼? '也許吧?語義完全不同。 – 2010-09-14 10:28:25

+0

C++中的集合也是如此,但他們有一個統一的添加元素的概念(請參閱我的問題的編輯)。 – 2010-09-14 10:54:10

+0

STL提供*許多*容器類型。我可以想象你想要一些簡單化。據我所知,你的問題只涉及列表和設置,當涉及到Python。如果你真的需要這樣的話,你可以隨時編寫自己的包裝器來包裝列表和集合,並按照你想要的方式運行。 – 2010-09-14 11:23:26

1

實際原因可能只是涉及到Python的歷史。

內置集合類型不是built-in until Python 2.6,它基於sets模塊,在Python 2.3之前它本身不在標準庫中。很顯然,改變集合類型的語義可能會破壞依賴於原始集合模塊的大量現有代碼,並且通常語言設計師會避免在沒有主要版本號的情況下破壞現有代碼。

如果你喜歡,你可以責怪原始模塊作者,但要記住,用戶定義類型和內置類型必須在Python 2.2之前存在於不同的Universe中,這意味着你不能直接擴展內置類型,並且可能允許模塊作者對沒有保持一致的集合語義感到滿意。

相關問題