Skip to content

Instantly share code, notes, and snippets.

@gerryjenkinslb
Last active November 6, 2018 23:27
Show Gist options
  • Save gerryjenkinslb/0d3a6173542c7b98859e14e4af95fe33 to your computer and use it in GitHub Desktop.
Save gerryjenkinslb/0d3a6173542c7b98859e14e4af95fe33 to your computer and use it in GitHub Desktop.

Python tuple detailed

A tuple is like a list - but safer, faster & smaller

A tuple is an array of object references
it is ordered, and indexed from zero
you cannot modify a tuple entry (immutable)

  • Note that entries in a tuple are references to an object,
    and you can't change which object the tuple points to for a given element.

advantages of tuples over lists:

  • faster, simpler, and less memory than lists
  • immutable feature leads to less possibility of bugs
    since it can't be changed after it is created
  • tuples can be used for keys in dictionary

Creating a tuple

t1 = (1, 1.4, 'hello', 22 + 5)  # using () with comma separated values/expressions
print(f't1: {t1}')

t2 = (55)  # This does not create a tuple but just the integer 55
print(f'\nt2 type: {type(t2)} value: {t2}')

t3 = (55,)  # trailing comma needed to create a tuple with one item
print(f't3 type: {type(t3)} value: {t3}')

# use the constructor with a generator, list, string or any other non infinite iterable
t4 = tuple(range(5))
t5 = tuple("hello") # -> ( 'h', 'e', 'l', 'l', 'o')
print(f'\nt4: {t4}\nt5: {t5}\n')

Visual showing how immutable works:

http://www.pythontutor.com/visualize.html#mode=edit

list1 = ['a', 'b', 'c']
tuple1 = (1, 2, list1)
tuple1[2][0] = 43
tuple1[1] = 'x'  # will cause error

A look at dir() of list vs. tuple

print('\n\n--list:')
print(dir(list()))
print(len(dir(list())))
    
print('\n\n--tuple:')
print(dir(tuple()))
print(len(dir(tuple())))
    
print('\n\n--diff (list - tuple):')
diff = set(dir(list())) - set(dir(tuple()))
print(diff)
print(len(diff))

tuple operations:

operation code, t is tuple description
len len(t) number of elements in t
in 43 in t true if 43 in t
min min(t) smallest value in t
max max(t) largest value in t
count t.count(3) number of times 3 occurs in t
constructor tuple(range(4)) new tuple from iterable
index t[3] fourth item in tuple
slice t[start:end:step] normal slice and variations same as lists
add (1,2) + (8,9) concatenate two tuples into new tuple (1,2,8,9)
multiply (1,9) * 3 concatenate itself 3 times (1,9,1,9,1,9)

what is packing/unpacking

packing: placing a list of values into a tuple
unpacking: copying values from a tuple into individual variables

Examples:

person1 = ("joe","thomas", 45, 54_300.00) # packing
print(person1)
person1 = "joe","thomas", 45, 54_300.00   # () are not needed
print(person1)

(first, last, age, salary) = person1     # unpacking
first, last, age, salary = person1       # () are not needed
print( f"first: {first}, last: {last}, age: {age}, salary: {salary}")


first, last, age, salary = "mary", "shelly", 33, 88_500.00
                        # Oh, this is parallel assignment
print( f"first: {first}, last: {last}, age: {age}, salary: {salary}")

packing/unpacking in function parameters

* used in front of a parameter in a call will unpack list or tuple

# first setup a function with three parameters
def print3(a,b,c): 
    print(a,b,c)

print3(1, 2, 3)

list1 = (1, 2, 3)
 
print3(*list1) # * causes unpacking of tuple or list into argument variables

* used in def of function before a parameter will pack parameters into tuple

def printn(*args): # packs parameters into tuple args
    print('len', len(args))
    print('args:', args)

printn(1, 2, 3)
printn(43)
printn(*list1, 4) # expand list1 into first three parameters and then 4 as fourth parameter

* in assignment on right side is unpacking

list1 = (1, 2)
list2 = (5, 6)
x = list1, list2
print(x)

x = *list1, *list2 # same as  list1 + list2
print(x)

x = list1 + list2
print(x)

* used on left for packing

first, *rest = (1, 2, 3, 4, 5)
print(f"first: {first}, rest: {rest}")

first, second, *rest = (1, 2, 3, 4, 5, 6)
print(f"first: {first}, second: {second}, rest: {rest}")

# *half1, *half2 = (1, 2, 3, 4, 5, 6) # can't do this

first, *mid, last = (1, 2, 3, 4, 5, 6)
print(f"first: {first}, mid: {mid}, last: {last}")

nested assignment by example

point1 = (1, 2)
point2 = (5, 6)
color = "blue"
line1 = (point1, point2, color)
print(f"line1: {line1}")

p1, p2, c = line1
print('p1, p2, c', p1, p2, c)
print(f"p1: {p1}, p2: {p2}, c: {c}")

(x1, y1), p2, c = line1
print('x1, y1, p2, c2:', x1, y1, p2, c)
print(f"x1: {x1}, y1: {y1}, p2: {p2}, c: {c}")

(x1, y1), (x2, y2), c = line1
print(f"x1: {x1}, y1: {y1}, x2: {x2}, y2: {y2}, c: {c}")

combine * and nesting

x = (1, 2, 3)
y = (7, 8, 9)
z = (x,y)  # ((1, 2, 3), (7, 8, 9))
(a, *b), (*c, d) = z
print(f"a: {a}, b: {b}, c: {c}, d: {d}")

Extra: python bytecodes for creating tuples

from dis import dis
def dis_this(stmt):
    print(stmt,":")
    print(dis(stmt))

dis_this('x = (a, b)')
dis_this('x = (1, 2)')
dis_this('x = (1, True, "hello", 1.5, 1+3.5j)')
dis_this('x = tuple(range(3))')
dis_this("x = (1,2,('green','blue','red'))")
dis_this("x = ([1,2],[3,4])")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment