為什麼 Python 裡面的 range 不包含上界?

例如 range(1,5),其實只包含1,2,3,4 即便是range(0,6,2),也不包含6。如果數不在range里那在range里出現這個數字的含義何在? 數組從0開始記數我已經忍了,range不含上界這是一個什麼意思?這還讓slice等等操作如何被人類理解啊? 另外,左閉右開是哪裡來的習慣?有什麼淵源? 題主贊同下列答案: 「range 的上界參數並非數學意義上的上界,而是計算意義上的跳出循環的條件(當把循環結構作用於這個 range 時,遇到「上界」,就意味著跳出);與 C / C++ 中數組指針為什麼被允許指向數組後面的一個元素的原因類似。題主可以查查 Andrew Koenig 在這方面非常細緻深入的討論。」 看見輪子老師的答案我不禁了解了一件事:程序員果然固執。。range 接受的第二個參數又不是數組長度,而是數組的上界。難道你要讓我們都認為range(1,6) 中的6是這個數組的長度?1,2,3,4,5 的長度是6?range(5,6) 6 是數組長度? 實際上我贊同range(start,end) 是對應於for(int i=start, i。。不要用C語言來辯解了。我學過C,我知道數組從0開始,但我無法理解range 不含上界。學習下matlab 和Mathematica 以及其他工程軟體中看看工程師和科學家怎麼想的吧,輪子哥。 另外本題的重點不是數組從0,而是range 的上界。不要抓住dijkstra 這朵奇葩不放謝謝。那個數學家定義的區間是不含右界的請告訴我。我必定謙恭學習


大家都喜歡左閉右開區間。


天天說什麼數學家數學家,題主你個學物理的就不要來指導江山教我們應該怎麼設計語言啊。儘管你很固執,我還是想開化開化你。

為什麼左閉右開,為什麼數組從0開始,這是因為C語言獲得一個數組a的元素地址a[b]就可以直接翻譯成a+b*sizeof(*a),免去了一次減法。這次減法在C語言剛發明的時候可是很重要的哦!然後你有一個長度s,那你遍曆數組用的for循環就是for(i=0;i&

好了,python又不是C語言,但是(據說)python的第一個實現是C寫的哦!幾乎所有語言受到C的影響全部都做成這樣了。當然有少部分的語言不是,譬如說Visual http://Basic.NET,譬如說我為我自己的www.gaclib.net 內置腳本引擎做的傻逼小腳本(最後發現swift的關鍵設計跟我的完全一致,太丟臉了)。這純粹看語言他爹的喜好。python他爹就不是什麼數學家,哈哈哈哈。

不過我們已經互相拉黑了,我也不用看到題主你的評論了,好開心。

Why are standard iterator ranges [begin, end) instead of [begin, end]?

樓下 @shell von 的一個鏈接,我發現數學家Dijkstra也是這麼想的。


可以這麼想,range 的上界參數並非數學意義上的上界,而是計算意義上的跳出循環的條件(當把循環結構作用於這個 range 時,遇到「上界」,就意味著跳出);與 C / C++ 中數組指針為什麼被允許指向數組後面的一個元素的原因類似。題主可以查查 Andrew Koenig 在這方面非常細緻深入的討論。

了解程序正確性證明的話,明確循環體結構的跳出條件是驗證程序正確性的重要步驟。而把 range 的上界直接設為跳出條件,大大方便了日常使用時對循環體跳出條件的設置,能避免不少犯錯的機會。而由於循環體在指令式語言的重要性,這樣的設計就有了基本的意義。

剛才查了一下 Python 的文檔,其實函數定義里已經把這一點明確下來了:range(start, stop[, step])。是 stop,不是 upper bound :)

如果需要包含最後一項的表達方式,可以參考 numpy.linspace 。其語法類似 range,但默認包含最後一項,除非設置參數 endpoint 為 False 。

註:俺不熟 Python @~@


印象中一共有四個表示方法[], (), [) (]。

然後要求r - l 為長度,只剩下兩個了[), (]

顯然前者更符合人們的邏輯。


不喜歡自己設計一個嘛,又不是什麼難事。


哪個數學家經常用到range

數學家的尊嚴何在!?


比較一下下面三種劃分實數的方案

[0, 1] (1, 2) [2, 3]…

(0, 1) [1, 2] (2, 3)…

[0, 1) [1, 2) [2, 3)…

顯然最後一種方案最美,所有區間包含的元素「一樣多」。

當然,這裡只是說明半開半閉/半閉半開作劃分是最合適的,兩者相比之下半閉半開更自然。


Why are standard iterator ranges [begin, end) instead of [begin, end]?


建議你還是用Basic語言好了,數組可以從1開始,for 可以 1 to 2這樣寫,不過題主好像是個軟黑。

——————————————————————————————————————————

python數組

&>&>&> s=[1,2,3,4,5,6]

&>&>&> s

[1, 2, 3, 4, 5, 6]

&>&>&> for i in range(0,6):

... print s[i]

其實來源於

c語言的數組

int arr[6]={0,1,2,3,4,5};//0 to 5...

數組遍歷

for(int i=0;i&printf("%d
",arr[i]);

}

ps:c語言常用i&<[長度]而不是i&<=[長度]-1。

1.i&<[長度]比較直觀

2.極端情況下,如果數組長度為0的話且使用了unsigned int,i&<=-1明顯是一個bug。

——————————————————————————————————————————

再舉個例子

2011年到2012年過了多少年,如果算左右界的話:

len(year[2011:2012])=2

這不符合常理

所以左右界中只能算一個

才是

len(year[2011:2012])=1


關於這個問題,我想應該是這樣:

我從c++ 裡面迭代器的內容嘗試解答一下這個問題,

對於一個容器,我們需要知道它的頭尾,最常進行的操作是從begin到end不斷+1來循環,此時如何知道循環到達末尾呢,如果end是上界(即包含這一個元素),我們還需對它的下一個元素拋出一個可以判別的信號,那麼end的意義就不大了,因此對循環而言,末尾的下一個元素更加重要,可以終止循環。

可以驗證這一想法的是,如果採用reversed 迭代器,那麼begin指向最後一個元素(包含),而此時的end指向第一個元素的前一個元素,對容器而言,是一個左開右閉的狀態,迭代器+1時實際上是向前走。

python中的range不也產生一個list么,遍歷總是需要退出的,左閉右開是因為我們總是從list左邊開始,遍歷到右邊結束。

希望有所幫助。


為何樓上都在說數組從0開始這個。我覺得和這個問題毫無關係。

其實程序里使用左閉右開的原因是:

考慮一個區間[l, r], 如果我需要遍歷這個區間,需要迭代器支持比較操作。

即:

i = l;
while (i &<= r) do { process(i); i++; }

而很多抽象的迭代器是無法來比較大小的,比如二叉樹里指向一個節點的指針。

而如果使用左閉右開區間[l, r),我們遍歷這個區間只需要迭代器支持比較相等操作就可以了。

即:

i = l;
while (i != r) do {
process(i);
i++
}

加if也不能遍歷左閉右閉的抽象區間。比如這樣:

i = l;
while (i != r) do {
process(i);
i++;
}
process(r);

但是這樣是無法處理空區間的。如果令[l, prev(l)]表示空區間,那麼上述代碼就會死循環,除非傳入一個新的參數來表示空區間。

就醬~


設計者:「爺樂意」


Ruby 歡迎你,1..6 和 1...6 隨你用。


不要用C語言來辯解了。我學過C,我知道數組從0開始,但我無法理解range 不含上界。

題主還是很實事求是的,只是說學過C,要是說會用C,那我現在已經瘋了……


基 0 的位元組數組的話,PDP-11 彙編里 a[i] 是這麼寫(假定 a 和 i 是局部變數):

MOV a(SP), R1
ADD i(SP), R1
MOV (R1), dst

基 1 的話,就要這麼干:

MOV a(SP), R1
ADD i(SP), R1
SUB #1, R1
MOV (R1), dst

多了一條指令,4 個位元組。

於是,BCPL 毅然決然選擇基 0。

於是,C 毅然決然選擇基 0。

於是一大批語言選擇基 0,包括 Python。

另外 C 裡面許多奇葩的設計都和 PDP-11 有關,比如後綴 ++ 算符就是 (Rn)+ 定址模式的直接體現;對局部變數指針目標的操作(處理 *a)也可以用 @X(SP) 在一條指令里完成。


這個不止python那麼搞吧...好處么range(6)正好是6個數,至於下標為什麼從0開始...baidu一下吧,答案很豐富,我是看了就忘,結論就從0開始好處多。

語法的事就別犟了,

謙虛的問為什麼說明你會思考

憤怒的問為什麼...每次我都會問自己我有語言的設計者nb嗎,然後就徹底泄氣了......默默baidu google stackoverflow去了...

來zhihu憤怒的問就是純屬吐槽,不思進取吧...


別犟嘴了,看官方doc不好么?

4.3 The range() Function

說白了,range(a, b)在設計的時候默認a是default as 0的,所以b本來就是當做offset或者說長度存在的一個arg,本來就不是tail index,當你的a不是default的時候,你自然而然以為「應該是一個頭一個尾兩個index啊?!」,很抱歉,其實不是的。

犟嘴不長學問。


就算是數學家,那也是從0開始!!!

下面我要說的是波蘭數學家謝爾品斯基的真實故事(度娘說是真實的,不能有假了吧!)

有一天,他要搬家,他的夫人把行李拿出來以後對他說:「我去叫輛計程車,你在這看好行李,總共有10個箱子。」

過一會兒,他的夫人回來了,他對夫人說道:

「剛才你說有10個箱子,可是我數了只有9個箱子。」

「不對,肯定是10個。」

「說什麼呢,我再數一遍,0,1,2,3……」

還有,在知乎上見過這麼一句話——可以不會,但不可以學不會,感覺你還沒有學會。


你可以看一下這篇文章《Python之父:為什麼Python數組下標從0開始》

原文:https://plus.google.com/115212051037621986145/posts/YTUxbXYZyfi(你的攀爬技術如何)

譯文:Python之父:為什麼Python數組下標從0開始


很多傳統什麼的大家都說很多了, 然後專門回答"為什麼"仨字好了, 因為發明者不湊巧喜歡了這些讓你不舒服的傳統


[a,b) + [b,c) = [a,c)

這樣不是很優雅么。

你們不是一天到晚問要優雅的做XXX么。


R語言適合你,題主


推薦閱讀:

CPython是什麼?PyPy是什麼?Python和這兩個東西有什麼關係呢?Python的底層使用什麼語言實現?學習Python需要學習底層實現嗎?
如何理解 Tornado ?
如何快速學會一個web框架?
如何開發一個Python web框架?
什麼時候應該從python2轉向python3?

TAG:Python | 編程 | 計算機 | Python框架 |