Python has a built-in tuple type that can be used to create immutable, ordered sequences of values. In the simplest case, a tuple is a pair of two values, such as keys and values from a dictionary:
Python有一個(gè)內(nèi)置的元組類型,可以用來(lái)創(chuàng)建不可變的、有序的值序列。在最簡(jiǎn)單的情況下,元組是一對(duì)值,比如字典的鍵值對(duì):
snack_calories = {
'chips ': 140,
'popcorn ': 80,
'nuts ': 190,
}
items = tuple (snack_calories.items ())
print (items)
>>>
( ( 'chips ', 140), ( 'popcorn ', 80), ( 'nuts ', 190))
The values in tuples can be accessed through numerical indexes:
元組中的值可以通過(guò)數(shù)值索引訪問(wèn):
item = ( 'Peanut butter ', 'Jelly ')
first = item[0]
second = item[1]
print (first, 'and ', second)
>>>
Peanut butter and Jelly
Once a tuple is created, you can’t modify it by assigning a new value to an index:
一旦元組被創(chuàng)建,你就不能通過(guò)給索引賦新值來(lái)修改它:
pair = ( 'Chocolate ', 'Peanut butter ')
pair [0] = 'Honey '
>>>
Traceback ...
TypeError: 'tuple ' object does not support item assignment
Python also has syntax for unpacking, which allows for assigning multiple values in a single statement. The patterns that you specify in unpacking assignments look a lot like trying to mutate tuples—which isn’t allowed— but they actually work quite differently. For example, if you know that a tuple is a pair, instead of using indexes to access its values, you can assign it to a tuple of two variable names:
Python的解包語(yǔ)法,允許它在一條語(yǔ)句中給多個(gè)變量同時(shí)賦值。解包賦值的模式看起來(lái)很像試圖改變?cè)M(這是不允許的),但它們實(shí)際上的運(yùn)行原理非常不同。例如,如果你知道一個(gè)元組是一對(duì),你可以將它賦值給兩個(gè)變量名,而不是使用索引來(lái)訪問(wèn)它的值:
item = ( 'Peanut butter ', 'Jelly ')
first, second = item # Unpacking
print (first, 'and ', second)
>>>
Peanut butter and Jelly
Unpacking has less visual noise than accessing the tuple’s indexes, and it often requires fewer lines. The same pattern matching syntax of unpacking works when assigning to lists, sequences, and multiple levels of arbitrary iterables within iterables. I don’t recommend doing the following in your code, but it’s important to know that it’s possible and how it works:
解包比訪問(wèn)元組的索引具有更少的視覺(jué)干擾,而且通常需要更少的行。當(dāng)給列表、序列和可迭代對(duì)象中任意級(jí)別的可迭代對(duì)象賦值時(shí),解包的匹配語(yǔ)法模式也同樣適用。我不建議在你的代碼中做以下事情,但重要的是你要知道這是可能的,以及它是如何工作的:
favorite_snacks = {
'salty ': ( 'pretzels ', 100),
'sweet ': ( 'cookies ', 180),
'veggie ': ( 'carrots ', 20),
}
( (type1, (name1, cals1)),
(type2, (name2, cals2)),
(type3, (name3, cals3))) = favorite_snacks.items ()
print (f 'Favorite {type1} is {name1} with {cals1} calories ')
print (f 'Favorite {type2} is {name2} with {cals2} calories ')
print (f 'Favorite {type3} is {name3} with {cals3} calories ')
>>>
Favorite salty is pretzels with 100 calories
Favorite sweet is cookies with 180 calories
Favorite veggie is carrots with 20 calories
Newcomers to Python may be surprised to learn that unpacking can even be used to swap values in place without the need to create temporary variables. Here, I use typical syntax with indexes to swap the values between two positions in a list as part of an ascending order sorting algorithm:
剛接觸Python的人可能會(huì)驚訝地發(fā)現(xiàn),解包甚至可以用于交換值,而不需要?jiǎng)?chuàng)建臨時(shí)變量。這里,作為升序排序算法的一部分,我使用典型的索引語(yǔ)法來(lái)交換列表中兩個(gè)位置的值:
def bubble_sort (a):
for _ in range (len (a)):
for i in range (1, len (a)):
if a [i] < a [i-1]:
temp = a [i]
a [i] = a [i-1]
a [i-1] = temp
names = [ 'pretzels ', 'carrots ', 'arugula ', 'bacon ']
bubble_sort (names)
print (names)
>>>
[ 'arugula ', 'bacon ', 'carrots ', 'pretzels ']
However, with unpacking syntax, it’s possible to swap indexes in a single line:
然而,使用解包語(yǔ)法,可以在一行中交換索引:
def bubble_sort (a):
for _ in range (len (a)):
for i in range (1, len (a)):
if a [i] < a [i-1]:
a [i-1], a [i] = a [i], a [i-1] # Swap
names = [ 'pretzels ', 'carrots ', 'arugula ', 'bacon ']
bubble_sort (names)
print (names)
>>>
[ 'arugula ', 'bacon ', 'carrots ', 'pretzels ']
The way this swap works is that the right side of the assignment (a [i], a[i-1]) is evaluated first, and its values are put into a new temporary, unnamed tuple (such as ( 'carrots ', 'pretzels ') on the first iteration of the loops). Then, the unpacking pattern from the left side of the assignment (a [i-1], a[i]) is used to receive that tuple value and assign it to the variable names a [i-1] and a[i], respectively. This replaces 'pretzels ' with 'carrots ' at index 0 and 'carrots ' with 'pretzels' at index 1. Finally, the temporary unnamed tuple silently goes away.
這種交換的工作方式是首先計(jì)算賦值的右側(cè)(a [i], a[i-1]),并將其值放入一個(gè)新的臨時(shí)的、未命名的元組(例如('carrot ', 'pretzels ')在循環(huán)的第一次迭代中)。然后,使用賦值左邊的解包模式(a [i-1], a[i])來(lái)接收該元組值,并將其分別賦給變量名a[i -1]和a[i]。在索引0中將“pretzels”替換為“carrots”,在索引1中將“carrots”替換為“pretzels”。最后,臨時(shí)的未命名元組悄然消失。
Another valuable application of unpacking is in the target list of for loops and similar constructs, such as comprehensions and generator expressions (see Item 27: “Use Comprehensions Instead of map and filter” for those). As an example for contrast, here I iterate over a list of snacks without using unpacking:
解包的另一個(gè)有價(jià)值的應(yīng)用是在for循環(huán)和類似結(jié)構(gòu)的目標(biāo)列表中,比如推導(dǎo)式和生成器表達(dá)式(參見(jiàn)第27項(xiàng):“使用推導(dǎo)式代替map和filter”)。作為對(duì)比的例子,我在這里不使用解包的方式迭代一個(gè)零食列表:
snacks = [ ( 'bacon ', 350), ( 'donut ', 240), ( 'muffin ', 190)]
for i in range (len (snacks)):
item = snacks [i]
name = item[0]
calories = item[1]
print (f '#{i+1}: {name} has {calories} calories ')
>>>
#1: bacon has 350 calories
#2: donut has 240 calories
#3: muffin has 190 calories
This works, but it’s noisy. There are a lot of extra characters required in order to index into the various levels of the snacks structure. Here, I achieve the same output by using unpacking along with the enumerate built-in function (see Item 7: “Prefer enumerate Over range”) :
這招管用,但有點(diǎn)嘈雜。為了索引零食結(jié)構(gòu)的不同層次,需要添加許多額外的字符。這里,我通過(guò)使用解包和enumerate內(nèi)置函數(shù)來(lái)實(shí)現(xiàn)相同的輸出(參見(jiàn)第7項(xiàng):“使用enumerate而不是range”):
for rank, (name, calories) in enumerate (snacks, 1):
print (f '#{rank}: {name} has {calories} calories ')
>>>
#1: bacon has 350 calories
#2: donut has 240 calories
#3: muffin has 190 calories
This is the Pythonic way to write this type of loop; it’s short and easy to understand. There’s usually no need to access anything using indexes.
這是python編寫這種類型循環(huán)的方法; 它很短并且很容易理解,通常不需要使用索引訪問(wèn)任何東西。
Python provides additional unpacking functionality for list construction (see Item 13: “Prefer Catch-All Unpacking Over Slicing”), function arguments (see Item 22: “Reduce Visual Noise with Variable Positional Arguments”), keyword arguments (see Item 23: “Provide Optional Behavior with Keyword Arguments”), multiple return values (see Item 19: “Never Unpack More Than Three Variables When Functions Return Multiple Values”), and more.
Python為列表提供了額外的解包功能(參見(jiàn)第13項(xiàng):" 使用全集解包而不是切片")、函數(shù)參數(shù)(參見(jiàn)第22項(xiàng):"使用可變位置參數(shù)減少視覺(jué)噪聲")、關(guān)鍵字參數(shù)(參見(jiàn)第23項(xiàng):"使用關(guān)鍵字參數(shù)提供可選行為")、多個(gè)返回值(參見(jiàn)第19項(xiàng):“當(dāng)函數(shù)返回多個(gè)值時(shí),不要解包超過(guò)三個(gè)變量”)等等。
Using unpacking wisely will enable you to avoid indexing when possible, resulting in clearer and more Pythonic code.
明智地使用解包將使您能夠在可能的情況下避免索引,從而生成更清晰、更符合python風(fēng)格的代碼。
Things to Remember
要記住的事
? Python has special syntax called unpacking for assigning multiple values in a single statement.
? Unpacking is generalized in Python and can be applied to any iterable, including many levels of iterables within iterables.
? Reduce visual noise and increase code clarity by using unpacking to avoid explicitly indexing into sequences.
? Python有特殊的解包語(yǔ)法,用于在單行語(yǔ)句中分配多個(gè)值。
? 解包在Python中很通用,可以應(yīng)用于任何可迭代對(duì)象,包括可迭代對(duì)象中的嵌套的多級(jí)別可迭代對(duì)象。
? 通過(guò)使用解包而不是顯示地使用序列索引,以減少視覺(jué)噪音,增加代碼清晰度。