這篇文章是閱讀Asabeneh的30 Days Of Python: Day 5 - Lists後的學習筆記與心得。
Python中串列(List)的定義類似JavaScript (以下簡稱JS)的陣列(array)。
建立一個空串列有兩種方式:
new Array()
empty_list = list()
empty_list = []
如果建立有值的串列也跟JS一樣:
greetings = ["Hello", "你好", "こんにちは"]
要取值的話還是跟JS一樣(not really):
greetings = ["Hello", "你好", "こんにちは"]
first_greeting = greetings[0]
print(first_greeting) # 'Hello'
print(greetings[1]) # '你好'
跟JS不太一樣的是可以接受負值,變成取倒數過來位置的值:
greetings = ["Hello", "你好", "こんにちは"]
last_greeting = greetings[-1]
print(last_greeting) # 'こんにちは'
print(greetings[-3]) # 'Hello'
可以想成是JS的解構賦值(destructuring assignment),不同的是,在Python必須連元素(items)個數都相符,不然會報錯:
colors = ["red", "green", "blue", "yellow", "orange", "purple"]
apple, leaf, sky = colors # ValueError
在這種情況下,可以利用*
加變數名稱來收集剩餘的值成另一個串列,像是JS的展開運算子(spread syntax):
colors = ["red", "green", "blue", "yellow", "orange", "purple"]
apple, leaf, sky, *mix = colors
print(apple) # 'red'
print(mix) # ['yello', 'orange', 'purple']
如同day 4中片取字串中字元提過:
colors = ["red", "green", "blue", "yellow", "orange", "purple"]
rgb = [0:3]
mixture = [-3:]
print(rgb) # ['red', 'green', 'blue']
print(mixture) # ['yellow', 'orange', 'purple']
跟JS陣列一樣,串列是可改動的(mutable):
colors = ["red", "green", "blue", "yellow", "orange", "purple"]
colors[2] = "cyan" # change "blue" to "cyan"
print(colors) # ['red', 'green', 'cyan', 'yellow', 'orange', 'purple']
可以使用in
這個運算子:
colors = ["red", "green", "blue", "yellow", "orange", "purple"]
has_yellow = "yellow" in colors
has_pink = "pink" in colors
print(has_yellow) # True
print(has_pink) # False
使用append(item)
這個方法,類似於JS的push()
:
colors = ["red", "green", "blue", "yellow", "orange", "purple"]
colors.append("pink")
print(colors) # ['red', 'green', 'blue', 'yellow', 'orange', 'purple', 'pink']
使用insert(index, item)
這個方法,類似JS的splice(index, 0, item)
;index
也可以接受負值:
colors = ["red", "green", "blue", "yellow", "orange", "purple"]
colors.insert(3, "teal")
colors.insert(-1, "pink")
print(colors) # ['red', 'green', 'blue', 'teal', 'yellow', 'orange', 'pink', 'purple']
remove(item)
方法如果有多個相符合的元素,會移除第一個,沒有符合的元素的話產生ValueError
:
# there are two "red" in the start and the end, respectively
colors = ["red", "green", "blue", "yellow", "orange", "purple", "red"]
colors.remove("red")
print(colors) # ['green', 'blue', 'teal', 'pink', 'yellow', 'orange', 'purple', 'red']
colors.remove("pink") # ValueError
pop([index = -1])
方法如果沒有指定index
值的話(預設是-1
),會跟JS的Array.prototype.pop()
一樣,會移除串列中最後一個元素。不然的話,會移除該index
值位置的元素;回傳值為移除的元素值:
colors = ["red", "green", "blue", "teal", "pink", "yellow", "orange", "purple"]
colors.pop() # 'purple'
print(colors) # ['red', 'green', 'blue', 'teal', 'pink', 'yellow', 'orange']
colors.pop(3) # 'teal'
print(colors) # ['red', 'green', 'blue', 'pink', 'yellow', 'orange']
del
keyword可以移除指定位置的值,或是移除整個串列:
colors = ["red", "green", "blue", "yellow", "orange", "purple"]
del colors[0]
print(colors) # ["green", "blue", "yellow", "orange", "purple"]
del colors[1]
print(colors) # ["green", "yellow", "orange", "purple"]
del colors[1:3]
print(colors) # ["green", "purple"]
# delete the list
del colors
print(colors) # NameError
類似JS的delete
,但index會更新,在JS中會造成,同樣的操作會把原本該位置的值變成undefined
:
const test = ["foo", "bar"];
delete test[0]; // returns true
console.log(test) // [empty, "bar"]
使用clear()
方法:
colors = ["red", "green", "blue", "yellow", "orange", "purple"]
colors.clear()
print(colors) # []
使用copy()
方法,可以複製現有串列的值到新串列中,類似JS中newArray = currentArray.slice()
的操作:
colors = ["red", "green", "blue", "yellow", "orange", "purple"]
rgb = colors.copy()
del rgb[3:6]
print(rgb) # ["red", "green", "blue"]
print(colors) # ["red", "green", "blue", "yellow", "orange", "purple"]
如果是使用指派的方式rgb = colors
,則會讓rgb
指向colors
的記憶體位址(copy by ref),對rgb
的改動會反映到colors
上,反之亦然,這點在JS上相同。
+
(plus operator)peripherals = ["keyboard", "mouse"]
computers = ["laptop", "desktop"]
bundles = peripherals + computers
print(bundles) # ['keyboard', 'mouse', 'laptop', 'desktop']
extend(iterable)
方法dogs = ["golden retriever", "labrador"]
animals = ["cat", "pig"]
animals.extend(dogs)
print(animals) # ['cat', 'pig', 'golden retriever', 'labrador']
使用count(item)
方法,回傳item
參數在串列中出現的次數:
ages = [18, 20, 25, 28, 32, 18, 21, 25]
print(ages.count(18)) # 2
使用index(item)
方法,回傳第一個找到的元素,沒有符合的元素的話產生ValueError
:
ages = [18, 20, 25, 28, 32, 18, 21, 25]
print(ages.index(25)) # 2
print(ages.index(24)) # ValueError
使用reverse()
方法,跟JS的Array.prototype.reverse()
一樣:
colors = ["red", "green", "blue", "yellow", "orange", "purple"]
colors.reverse()
print(colors) # ['purple', 'orange', 'yellow', 'blue', 'green', 'red']
使用sort(*, key=None, reverse=False)
方法,如果有給reverse=True
參數的話,會變成降冪(descending order)排列;如果有給key=fn
的話會在排序時對每個元素執行fn
再以執行後的元素值排序,但不會改變原有的元素值:
ages = [18, 20, 25, 28, 32, 18, 21, 25]
ages.sort()
print(ages) # [18, 18, 20, 21, 25, 25, 28, 32]
ages.sort(reverse=True)
print(ages) # [32, 28, 25, 25, 21, 20, 18, 18]
colors = ["red", "green", "blue", "Yellow", "orange", "purple"]
colors.sort()
print(colors) # ['Yellow', 'blue', 'green', 'orange', 'purple', 'red']
# sorting in lowercase char order
colors.sort(key=str.lower)
print(colors) # ['blue', 'green', 'orange', 'purple', 'red', 'Yellow']
使用sorted(iterable, /, *, key=None, reverse=False)
函式,會回傳排序後的串列,不會修改原始串列:
ages = [18, 20, 25, 28, 32, 18, 21, 25]
sorted_ages = sorted(ages)
print(sorted_ages) # [18, 18, 20, 21, 25, 25, 28, 32]
print(ages) # [18, 20, 25, 28, 32, 18, 21, 25]
sorted_ages_desc = sorted(ages, reverse=True)
print(sorted_ages_desc) # [32, 28, 25, 25, 21, 20, 18, 18]
colors = ["red", "green", "blue", "Yellow", "orange", "purple"]
sorted_colors = sorted(colors)
print(sorted_colors) # ['Yellow', 'blue', 'green', 'orange', 'purple', 'red']
print(colors) # ['red', 'green', 'blue', 'Yellow', 'orange', 'purple']
sorted_colors_by_lowercase = sorted(colors, key=str.lower)
print(sorted_colors_by_lowercase) # ['blue', 'green', 'orange', 'purple', 'red', 'Yellow']
sort()
有所不同參考James Yoo的Sort Function in JavaScript and Python
文章中舉了很清楚例子:
const arr = [-1, -10, -2, 3, 4, 5];
arr.sort();
console.log(arr); // [-1, -10, -2, 3, 4, 5]
arr = [-1, -10, -2, 3, 4, 5];
arr.sort()
print(arr) // [-10, -2, -1, 3, 4, 5]
在官方文件#list.sort寫的參數說明中有個*
符號,這是指keyword-only,簡單來說,它會鎖住這個函式(方法)呼叫時要使用的引數名稱,所以sort(True)
不行。
更多例子可以參考:Forced naming of parameters in Python | stackoverflow]
另外Python 3.8以上,可以在參數中加入/
符號標示positional-only,相關例子可以參考:What is the meaning of a forward slash "/" in a Python method signature, as shown by help(foo) | stackoverflow