8y8y8y[[[[[[yy_yhy=[[hyy[[yy[y[VwPy[[VwEy[[ywh[wh[hy[hh[hh[hhj[hyk8hy[hy[h[hhK[hEy_-lyy-D[EyNjnVnynn[nNjyn[hynwph[Mp|whph[}}hhyyWPlplznwphyhyhe=nwp[yy[[[jy[[;y[yRyy}[jyRyyy}[iBbbAfCAeCfACABBrEErAX-~~~| 6A6A64VCB~ 6F-~CWC 6866V 6A64VCC 6464V~Z~~ 6887797VCB 864756475VBCC 65656565VC 68494V 764}AW 6A6R64V~CC 699VC 8496964V~~ 49765V 558468}4-~~CC 66F8-~BZX

Tuple.` Consider this starfish. It has 5 arms. It is underwater. These attributes form a unit of information—they could be stored together in a tuple.`Python tuples` are values—they never change. Suppose an element has a shape and a color. This forms a tuple pair. Logically this information is a single unit.`Create.` A tuple is immutable—this is important to consider. It cannot be changed after created. So the creation syntax must be used often. We use "(" and ")" to create tuples. `Zero elements: `To create a tuple with zero elements, use only the two parentheses "()".`One element: `For a tuple with one element, use a trailing comma. This helps Python tell that you don't mean an expression, such as (1 + 2).`Two elements: `For a tuple with 2 or more elements, use a comma between elements. No ending comma is needed.`Immutable.` An immutable object cannot be changed. Once created it always has the same values. A tuple is immutable. Here we attempt to assign the first element in the tuple. `But: `This is invalid. When executed, the Python runtime will report a TypeError.`Error `error-python`Create: `To make a new, changed tuple, we would need to create a new tuple. We could specify that some items have the same values.`Immutability.` This part is kind of boring. But the concept of immutable objects is important. It seems inefficient. Why not just modify existing objects? `Dictionary: `Some objects are more efficient when they are immutable. For example, in a dictionary tuples are used.`We can directly access these two-element tuples. If these tuples could be changed, the original dictionary would become invalid.`Pack, unpack.` Tuples can be packed and unpacked. In packing, we place values into a new tuple. And in unpacking we extract those values back into variables. `This syntax form creates elegant and small programs. In this program we pack two strings into a tuple.`Then: `We initialize two variables to those two packed values. The variables act like any other variable.`No parentheses.` Tuples are typically specified with surrounding parentheses chars. But suppose you are a wild one. You can just use a comma. The tuple is inferred. `Add, multiply.` A tuple is not a number. But it can be added to or multiplied. By adding two tuples, they are concatenated. One is put after the other. `By multiplying a tuple with a number, we add the tuple to itself a certain number of times.`Warning: `This syntax form can become somewhat confusing. I have not used it often on tuples.`Divide, subtract.` We cannot divide or subtract tuples. Out of curiosity I tried this. I received the TypeError with "unsupported operand type." `Operand: `As a reminder, an operand is a value on one side of an expression. It is part of an operation.`Max, min.` The max and min functions can be used on tuples. These functions locate the item that would be sorted last (max) or sorted first (min). `Max, min `max-python`For strings: `The comparison performed is alphabetical—"able" comes before "zero". So "able" would be less than "zero".`For numbers: `The comparison is numeric—10 comes before 20. These comparisons are logical.`In keyword.` This example creates a two-element tuple (a pair). It searches the tuple for the string "cat". It then searches for "bird", but this string does not exist. `With the in-keyword, we can search a tuple. We use in as part of an if-statement. And we can combine in with not—this is "not in".`In `in-python`Slice.` A tuple can be sliced. The slice notation uses a colon. On the left side of the colon, we have the starting index. If no starting index is present, the program uses 0. `Slice `slice-python`On the right side of the colon, we have the ending index. If no ending index is present, the last index possible is used.`Slicing creates a new tuple. A slice that specifies no indexes is a simple way to copy a tuple.`Index.` This gets the index of an element. Here we search for the value "dog," and get the index 1 (the second position). If we use index() on a value that is not found, an error results. `Consider the in operator before calling index() on a value that might not exist. This prevents a possible exception.`Count.` This returns the number of elements with a specific value in a tuple. If you need to get the total length of the tuple, please use len. Count only counts certain values. `Keys, dictionary.` We next use a tuple as a dictionary key. Dictionaries can use tuple keys without worrying about them changing. Here we use the pair of values 1 and 2 to look up a value. `You can use tuples in this way to create a two-dimensional dictionary. Use a tuple to represent X and Y coordinates.`Convert.` A tuple cannot be modified. But a list can be changed in many ways. For this reason we often need to convert a tuple into a list. `List: `The list built-in accepts a tuple as its argument. Here we use sort() on the resulting list.`Finally: `In the program, we convert the list back into a tuple. This is done with the tuple() function.`We see that a list has square brackets. A tuple has round ones. This is an important part of Python's syntax.`Enumerate.` This is a built-in method. Enumerate() returns a tuple of an index and the element value at that index. It is often used on a list. `We use enumerate on a list of strings. We can access the tuple, or directly unpack the tuple in the for-statement.`List of tuples.` Let us examine a practical example. This program divides a string into a list of tuples. Each tuple has adjacent characters from the string. `Range: `We use the range built-in to iterate over the string, with a step of 2. We start at index 1 to avoid the first char.`Append: `We call append() on the list (called "pairs") and as the argument to append, we create a two-element tuple (a pair).`Swap.` To flip or swap variables, we do not need a temporary variable. We can use a tuple unpacking expression. We assign each variable to the other one in a single statement. `Performance.` How do we choose between the syntax forms for tuples? In this benchmark we test two ways of assigning variables to values in a tuple. We unpack tuples. `Version 1: `This version of the program uses a single statement to unpack an existing tuple.`Version 2: `This version assigns to the elements in a tuple using the "[" and "]" syntax.`Result: `Version 1, which unpacks the tuple in a single statement, is somewhat faster.`In Python, the number of statements often influences greatly the results. This may change as more advanced compilers appear.`Research.` A tuple is a sequence, much like a list (and not like a class). In the Python documentation, we find that the enumerate() built-in returns tuples. `Quote: `Tuples are immutable sequences, typically used to store collections of heterogeneous data (such as the 2-tuples produced by the enumerate() built-in).`Built-in Types: python.org `https://docs.python.org/3/library/stdtypes.html`Namedtuple.` In normal tuples, fields have no names. With namedtuple, a type from the collections module, we can provide names to a tuple's fields. `Namedtuple `namedtuple-python`With tuples,` we have access to many (but not all) of the methods of a list. Tuples are key to other important types, such as dictionary. And they are used, to some advantage, within lists.`Usage.` Tuples are often combined with other types. Often we store tuples within lists to create a list of pairs. In this way we avoid combining values together in strings.

JKN N# Zero-K tuple. NaKN()N # One-K tuple. NbKN("one",)N # Two-K tuple. NcKN("one", "two")N K(a) K(len(a)) K(b) K(len(b)) K(c) K(len(c)) N () 0 ('one',) 1 ('one', 'two') 2N tupleK('cat', 'dog', 'mouse')N # This causes an error. Ntuple[0]K'feline' NResultsN TypeError: 'tuple' object does not support item assignmentN N# CK packed tuple. NpairK(N"dog"N, N"cat"N)N # Unpack tuple. N(key, K)KpairN # K unpacked variables. NK(key) K(K) N dog catN N# A trailing comma indicates a tuple. None_itemKN"cat",N # A tuple can be specified with no parentheses. Ntwo_itemsKN"cat", "dog"N K(one_item) K(two_items) N ('cat',) ('cat', 'dog')N checksK(10, 20, 30)N # Add two tuples. NmoreKchecks N+N checks K(more)N # Multiply tuple. NtotalKchecks N*N 3 K(total) N (10, 20, 30, 10, 20, 30) (10, 20, 30, 10, 20, 30, 10, 20, 30)N N# MaxKmin KKs. NfriendsK(N"sandy"N, N"michael"N, N"aaron"N, N"stacy"N) K(NmaxN(friends)) K(NminN(friends))N # MaxKmin KKs. NearningsK(1000, 2000, 500, 4000) K(NmaxN(earnings)) K(NminN(earnings)) N stacy aaron 4000 500N pairK(N"dog"N, N"cat"N)N # Search Ka K. Nif N"cat"N NinN pair: JK(N"Cat found"N)N # Search Ka K not present. Nif N"bird"N Nnot inN pair: JK(N"Bird not found"N) N Cat found Bird not foundN KsK(1, 3, 5, 7, 9, 11, 13)N # Copy the tuple. NK(Ks[N:N])N # Copy all Ks at index 1 or more. NK(Ks[N1:N])N # Copy one K, starting at first. NK(Ks[N:1N])N # Copy Ks from index 2K4. NK(Ks[N2:4N]) N (1, 3, 5, 7, 9, 11, 13) (3, 5, 7, 9, 11, 13) (1,) (5, 7)N N# Three-item tuple. NitemsK(N"cat"N, N"dog"N, N"bird"N)N # Kindex of K with K "dog". NindexKitems.NindexN(N"dog"N) K(index, items[index]) N 1 dogN KsK(1, 2, 2, 3, 3, 3) K(Ks.NcountN(1)) K(Ks.count(3))N # There are no 100 Ks, so this Ks 0. NK(Ks.count(N100N)) N 1 3 N0N N# A tuple with two Ks. NpairKN(1, 2)N # CK a dK. # KUse the tuple as a key. NdictK{} dict[pair]KN"Python"N # Access the dK Ka tuple. NK(dict[N(1, 2)N]) N PythonN N# Tuple containing unsorted odd Ks. NoddsK(9, 5, 11)N # CKKKKsort. NKKNKN(odds) K.sort() K(K)N # CK backKtuple. Nsorted_oddsKNtupleN(K) K(sorted_odds) N [5, 9, 11] (5, 9, 11)N KsK[N"meow"N, N"bark"N, N"chirp"N]N # Use enumerate on K. NKpairKNenumerateN(Ks):N J# The pair is a 2-tuple. JNK(pair)N # Unpack enumerate's KsKK-loop. NKindex, KKNenumerateN(Ks):N J# We have already unpacked the tuple. JNK(str(index)KN"..."NKK) N (0, 'meow') (1, 'bark') (2, 'chirp') 0...meow 1...bark 2...chirpN KKN"abcdefgh"N pairsK[]N # Kover K. # KUse step of 2Krange built-in. # KExtract pairs of letters Ko a K of tuples. NKiKNrangeN(1, len(K), 2): JoneKK[i - 1] JtwoKK[i] Jpairs.NaKN((one, two))N # K K of tuple pairs. NKNpairNKpairs: JK(pair) N ('a', 'b') ('c', 'd') ('e', 'f') ('g', 'h')N leftKN"cat"N rightKN"dog"N K(N"LEFT"N, left) K(N"RIGHT"N, right) K(N":::FLIP:::"N)N # Use tuple unpackingKflip variables. Nleft, rightKright, left K(N"LEFT"N, left) K(N"RIGHT"N, right) N LEFT cat RIGHT dog N:::FLIP:::N LEFT dog RIGHT catN Ktime pairK(1, 2) K(time.time())N # Version 1: unpack tuple. NiK0 K i < 10000000: J(a, b)Kpair JiKiK1 K(time.time())N # Version 2: assign variablesKtuple separately. NiK0 K i < 10000000: JaKpair[0] JbKpair[1] JiKiK1 K(time.time()) NResultsN 1345673733.21 1345673737.12 (Unpack: N3.91 sN) 1345673742.12 (Assign: N5.00 sN)N

0.-1f9[/\UUi7Y^/0creates tuplesassigns tupleassigns variablestuples, no parenthesesadds and multiples tuplesmax and minsearches tuplestuple slicesindexcounttuples as dictionary keysconverts tuple and listenumeratelist of tuplesflips variablesbenchmarks tuple