<jupyter_start><jupyter_text>5 STRUCTURED TYPES, MUTABILITY, AND HIGHERORDER FUNCTIONSThe numeric types `int` and `float` are **scalar(标量)** types. That is to say, objects of these types have **no accessible internal structure**. In contrast, `str` can be thought of as a `structured, or non-scalar`, type. One can use indexing to extract individual characters from a string and slicing to extract substrings.In this chapter, we introduce `four additional structured types`. * tuple(元组）, is a rather simple generalization of `str`. * list(列表）* range* dict(字典） —are more **interesting**. We also return to the topic of functions with some examples that illustrate the utility of being able to treat functions in the same way as other types of objects.  5.1 TuplesLike `strings`, **tuples** are immutable ordered sequences of elements. The difference is that the elements of a tuple need not be characters. The individual elements can be ofany type, and need not be of the same type as each otherLiterals of type `tuple` are written by enclosing a comma-separated , list of elements within parentheses( )<jupyter_code>t1 = () # empty tuple

t2 = (1, 'two', 3) #  1）any type; 2） not be of the same type as each other.
student=('Name',22)
print(t1)
print(t2)
print(student)<jupyter_output>()
(1, 'two', 3)
('Name', 22)<jupyter_text>Looking at this example, you might naturally be led to believe that the tuple containing the `single value 1` would be written `(1)`. But, to quote [Richard Nixon](https://en.wikipedia.org/wiki/Richard_Nixon), `“that would be wrong.”`Since parentheses`( )` are used to `group expressions`,(1) is `merely` a verbose way to write the `integer 1`.<jupyter_code>a=(1)
a
b=(a+2,)
b
a=(1,)
a<jupyter_output><empty_output><jupyter_text>To denote the singleton tuple containing this value, we write (1 ,)**Almost everybody who uses Python has at one time or another accidentally omitted that annoying `comma`.**<jupyter_code>expre=('10+1')

tsingleton=('10+1',)  # comma-separated 

print(expre)
print(type(expre))

print('\nThe singleton tuple containing this value')
print(tsingleton)
print(type(tsingleton))<jupyter_output><empty_output><jupyter_text>**Repetition** can be used on tuples. For example, the expression `3*('a', 2)` evaluates to `('a', 2, 'a', 2, 'a', 2).`<jupyter_code>3*('a', 2)<jupyter_output><empty_output><jupyter_text>Like string ,Tuples can be concatenated, indexed, and sliced.(indexing starts at 0)concatenated<jupyter_code>t1 = (1, 'two', 3)

t2 = (t1, 3.25)   #  any type,tuples can contain tuples

print('t2=',t2)

print('t1+t2=',t1 + t2)  # + concatenated<jupyter_output>t2= ((1, 'two', 3), 3.25)
t1+t2= (1, 'two', 3, (1, 'two', 3), 3.25)<jupyter_text>indexed<jupyter_code>print('(t1 + t2)[3]=',(t1 + t2)[3]) # [3] indexed tuple :as always in Python, indexing starts at 0<jupyter_output>(t1 + t2)[3]= (1, 'two', 3)<jupyter_text>sliced.(indexing starts at 0)<jupyter_code>print('(t1 + t2)[2:4]=',(t1 + t2)[2:4]) # [2:5] sliced<jupyter_output>(t1 + t2)[2:4]= (3, (1, 'two', 3))<jupyter_text>The second assignment statement binds the name t2 to a tuple that contains the tuple to which t1 is bound and the floating point number 3.25. This is possible because a tuple, like everything else in Python, is an object, so tuples can contain tuples.Therefore, the first print statement produces the output,```python((1, 'two', 3), 3.25)```The second print statement prints the value generated by concatenating the values bound to t1 and t2, which is a tuple with five elements. It produces the output```python(1, 'two', 3, (1, 'two', 3), 3.25)```The next statement selects and prints the fourth element of the concatenated tuple (as `always` in Python, `indexing starts at 0`), and the statement after that creates and prints a slice of that tuple, producing the output```python(1, 'two', 3)(3, (1, 'two', 3))```  Tuples are immutable    The tuples cannot be modified after they are created. if you try to modify one of the elements of the tuple, you get an error:```pythonTypeError: 'tuple' object does not support item assignment```<jupyter_code>t1 = (1, 'two', 3)
t1[0]='A'<jupyter_output><empty_output><jupyter_text>Because tuples are immutable, you can’t modify the elements. You can replace one tuple with another,This statement makes a **new tuple** and then makes `t1` refer to it.<jupyter_code>t1 = ('A',) + t1[1:]
t1<jupyter_output><empty_output><jupyter_text>`for` e  in seqA for statement can be used to iterate over the elements of a `tuple`.<jupyter_code>t1 = (1, 'two', 3)
for e in t1:
    print(e) 
def intersect(t1, t2):
    """Assumes t1 and t2 are tuples
        Returns a tuple containing elements that are in
        both t1 and t2
    """
    result = ()
    for e in t1:
        if e in t2:
            result = result + (e,)
    return result

t1 = (1,2, 'two', 3,4)
t2 = (1,4)
result=intersect(t1, t2)
print(result)<jupyter_output><empty_output><jupyter_text>Operators and Functions on tuplesYou can operate on tuples using (supposing that tup is a tuple):    * built-in functions such as `len(tup)`;* built-in functions for tuple of numbers such as `max(tup), min(tup) and sum(tup)`Tuple methods: * `count(e)` : counts the number of occurrences of a value e* `index(e)`: return the index of the first  occurrences of e in tup,or error<jupyter_code>tup=(1,2,2,3)
len(tup)
max(tup), min(tup), sum(tup)
tup.count(2)
tup.index(4)<jupyter_output><empty_output><jupyter_text>5.2 Sequences and Multiple AssignmentIf you know the length of a sequence (e.g., a tuple or a string),it can be convenient to use Python’s multiple assignment statement to extract the individual elements.* **Sequence unpacking**<jupyter_code># Sequence unpacking
x, y ,z= (3, 4,5)
a, b, c = 'xyz'

print('x=',x,' y=',y)
print('a=',a,' b=',b,' c=',c)<jupyter_output>x= 3  y= 4
a= x  b= y  c= z<jupyter_text>This mechanism is particularly convenient when used in * conjunction with functions that return `fixed-size` sequences.<jupyter_code>def bisection(func,low,high,k,epsilon):
    ans = (high + low)/2.0
    numGuesses = 0
    while abs(func(ans,k)) >= epsilon:
        numGuesses += 1
        if ans**2 < k:
            low = ans
        else:
            high = ans
        ans = (high + low)/2.0
    return ans,numGuesses
def func1(x,k):
    return x**2-k

k = 25
epsilon = 0.01
low = 0.0
high = max(1.0, k)   # build-in function

ans,numGuesses=bisection(func1,low,high,k,epsilon)
print('numGuesses =', numGuesses)
print(ans, 'is close to square root of', k)
# tuple 
results = bisection(func1,low,high,k,epsilon)  
print(results)
print('ans=', results[0])
print('numGuesses=', results[1])<jupyter_output>(5.00030517578125, 13)
ans= 5.00030517578125
numGuesses= 13
{'fraction_non_alphanumeric': 0.1315240083507307, 'fraction_numerical': 0.03355204294661497, 'mean_word_length': 4.9564831261101245, 'pattern_counts': {'":': 0, '<': 48, '<?xml version=': 0, '>': 48, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '237919', 'license': 'MIT', 'n_tokens_mistral': 2438, 'n_tokens_neox': 2278, 'n_words': 832, 'path': 'notebook/Unit1-4-1-Tuple.ipynb', 'repo_name': 'alex-treebeard/home', 'size': '6706'}