0% found this document useful (0 votes)
11 views40 pages

06 SetTupleDictionaryYield-1

Uploaded by

haeinpark1376
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views40 pages

06 SetTupleDictionaryYield-1

Uploaded by

haeinpark1376
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 40

Lecture 06

Sets, Tuples, Dictionaries, Yield

Hyeong-Seok Ko
Seoul National University
Dept. of Electrical and Computer Engineering
Contents
• Sets
• Tuples
• Dictionaries
• Yield and Iterator
Sets
Set
• An unordered collections of unique elements
– Does not support indexing, or other sequence-based operation
– Sets cannot contain mutable elements (such as lists or dictionaries)

S1 = {1, 2, 5, "hello"}

L1 = [42, 3.14159, "hello", ["banana", "apple"]]


S2 = {42, 3.14159, "hello", ["banana", "apple"]} # error!
Set
L = [42, 3.14159, "hello"]
S1 = {42, 3.14159, "hello"}
S2 = {"hello", 3.14159, 42, 3.14159, "hello"}

print(S1)
print(S2)

for item in S2 :
print(item, end=" ")
print()

{42, 3.14159, 'hello'}


{42, 3.14159, 'hello'}
42 3.14159 hello
End Parameter for print()

print(1) print(1,end='')
print(2) print(2, end='')
print(3) print(3)

1 123
2
3 print(1,end=' ')
print(2, end=' ')
print(3)

1 2 3

• The end parameter defines the line terminator for the print function.
• By default, end = “new line”, i.e., “\n"
• By having end = ‘ ‘ or ‘ ‘, you can avoid new line.
Sep Parameter for print()

>>> print(1, 2, 3)
1 2 3
>>> print('1\n2\n3')
1
2
3
>>> print(1, 2, 3, sep='\n')
1
2
3

• The sep argument defines the separator between the arguments to print.
• sep='\n' tells, after printing each item, to put the separation character.
• By default, sep = “space” which is known as “soft spacing”.
• You can also use \t, \\, etc. as sep.
Useful Functions/Operations for Set
• Basic set operations
– Intersection & A = {1, 2, 3}
B = {2, 3, 4}
– Union | print(A&B)
– Difference - print(A|B)
• Practice more in the following 2 pages print(A-B)

{2, 3}
{1, 2, 3, 4}
{1}
Type&Run: add, update, discard, clear, remove,…
Source code Result
s1 = set() set() empty set
print(s1) {1, 3}
s1.add(1) {1, 3, 5, 7, 9}
s1.add(3)
print(s1) {1, 3, 5, 7, 9}
s1.update({3, 5, 7, 9}) adds multiple elements {1, 5, 7, 9}
print(s1, '\n') {1, 5, 7, 9}
{5, 7, 9}
s1_copy = s1.copy()
print(s1_copy) False
s1_copy.discard(3) False True
print(s1_copy) True False
s1_copy.discard(2)
#s1_copy.remove(2) if not present, produces error {5, 7, 9}
print(s1_copy) set()
s1_copy.pop() randomly removes one element
print(s1_copy, '\n')

print(s1.isdisjoint(s1_copy))
print(s1.issubset(s1_copy), s1_copy.issubset(s1))
print(s1.issuperset(s1_copy), s1_copy.issuperset(s1), '\n')

print(s1_copy)
s1_copy.clear()
print(s1_copy)
Type&Run: difference, intersection, union
Source code Result
s1 = {1, 3, 5, 7, 9} {1, 3, 5, 7, 9} {8, 2, 4, 6} {1, 3}
s2 = {2, 4, 6, 8} {1, 3, 5, 7, 9} {9, 5, 7} {9, 5, 7}
s3 = {1, 3} {1, 3, 5, 7, 9} {9, 5, 7} {5, 7, 9}

print(s1, s2, s3) set() {1, 3} set()


print(s1 - s2, s1 - s3, s1 - s2 - s3) set() {1, 3} set()
print(s1.difference(s2), s1.difference(s3), s1.difference(s2, s3))
#s1.difference_update(s2) means s1 -= s2 {1, 2, 3, 4, 5, 6, 7, 8, 9} {5, 7, 9} {2, 4, 5, 6, 7, 8, 9}
#s1.difference_update(s3) {1, 2, 3, 4, 5, 6, 7, 8, 9} {5, 7, 9}
#s1.difference_update(s2, s3)
{1, 2, 3, 4, 5, 6, 7, 8, 9} {1, 3, 5, 7, 9}
print() {1, 2, 3, 4, 5, 6, 7, 8, 9}
print(s1 & s2, s1 & s3, s1 & s2 & s3) {1, 2, 3, 4, 5, 6, 7, 8, 9} {1, 3, 5, 7, 9}
print(s1.intersection(s2), s1.intersection(s3), s1.intersection(s2, s3)) {1, 2, 3, 4, 5, 6, 7, 8, 9}
#s1.intersection_update(s2)
#s1.intersection_update(s3)
#s1.intersection_update(s2, s3)

print()
print(s1 ^ s2, s1 ^ s3, s1 ^ s2 ^ s3) # s1^s2 = (s1-s2)|(s2-s1)
print(s1.symmetric_difference(s2), s1.symmetric_difference(s3))
#s1.symmetric_difference_update(s2)
#s1.symmetric_difference_update(s3)

print()
print(s1 | s2, s1 | s3, '\n', s1 | s2 | s3)
print(s1.union(s2), s1.union(s3), '\n', s1.union(s2, s3))
Tuples
Tuple ["banana",
42 3.14159 "hello"
"apple"]

T1 = (42, 3.14159, "hello", ["banana", "apple"])


print(T1)

(42, 3.14159, 'hello', ['banana', 'apple'])

• A read-only ordered sequence of values L = [42, 3.14159, "hello"]


T2 = (42, 3.14159, "hello")
– A sequence type print(type(T2))
– Each value is identified by an index for item in T2:
print(item, end = " ")
– Like list, each element can have any type
print()
– Differently from list, tuple is immutable (i.e., read only)
print(T2[0])
T2[0] = 1 # illegal: read only

<class 'tuple'>
42 3.14159 hello
42
Error
More about Tuple

T = (42, 3.14159, "hello") 42 3.14159 hello


a,b,c = T # multiple assignments 3.14159 42
print(a,b,c)

a,b = b,a # swapping


print(a,b)

T = (42, 3.14159, "hello") <class 'tuple'> (42, 3.14159, 'hello')


L = list(T) # type conversion <class 'list'> [42, 3.14159, 'hello']
S = set(T) # type conversion <class 'set'> {'hello', 42, 3.14159}
print(type(T), T)
print(type(L), L)
print(type(S), S)
Type&Run: indexing, slicing, concatenating, repeating
Source code Result
t = ('concepts', 'and', ['practices', 'of'], 'computer') Indexing
print('Indexing') ('concepts', 'and', ['practices', 'of'], 'computer')
print(t) concepts and ['practices', 'of'] computer
print(t[0], t[1], t[2], t[3]) computer ['practices', 'of'] and concepts
print(t[-1], t[-2], t[-3], t[-4]) c practices o r t
print(t[0][0], t[2][0], t[2][1][0], t[3][-1], t[-1][-3])
print() Slicing
('concepts', 'and')
print('Slicing') (['practices', 'of'], 'computer')
print(t[0:2]) ('concepts', 'and', ['practices', 'of'])
print(t[2:]) ('concepts', 'and', ['practices', 'of'], 'computer')
print(t[:3]) ('concepts', 'and', ['practices', 'of'], 'computer')
print(t[:])
# t[0:2] = ('CONCEPTS', 'AND') produces error Concatenating
print(t) ('concepts', 'and', ['practices', 'of'], 'computer', 'python', '001')
print()
Repeating
print('Concatenating') ('a', 'b', 'cd', 'a', 'b', 'cd')
print(t + ('python', '001')) ('a', 'b', 'cd', 'a', 'b', 'cd', 'a', 'b', 'cd')
print()

print('Repeating')
print(2*('a', 'b', 'cd'))
print(('a', 'b', 'cd')*3)
Type&Run: finding out the index

Source code Result


t = (123, 4.56, True, 'abc', 4.56) (123, 4.56, True, 'abc', 4.56)
1
print(t) 1
print(t.count(123)) 4
print(t.index(4.56))
print(t.index(4.56, 2))
#print(t.index(4.56, 2, 4)) #error
Type&Run: list()

Source code Result


# tuple to list ['I', 'am', 'a', 'tuple']
T = ('I', 'am', 'a', 'tuple') ['I', 'am', 'a', 'set']
print(list(T))

# set to list
S = {'I', 'am', 'a', 'set'}
print(list(S))
Dictionaries
Dictionary
• An unordered set of key:value pairs
– Indexed by the keys
– The keys should be unique within the dictionary
– The values are mutable, but keys are immutable

D = {"apple":1500, "banana":1000, 15:"monkey"} keys values


print(type(D), D) “apple” 1500
print(D["apple"], D[15])
D["apple"] = 500 “banana” 1000
print(D["apple"]) 15 “monkey”
print(D[0])

<class 'dict'> {'apple': 1500, 'banana': 1000, 15: 'monkey'}


1500 monkey
500
Error
Useful Functions
D = {"apple":1500, "banana":1000, 15:"monkey"}
• items(): Retrieves key-value pairs for t in D.items(): print(t, end = ", ")
• keys(): Retrieves keys print()
for a,b in D.items(): print(a, b, end = ", ")
• values(): Retrieves values print()
• get(key, default value): for t in D.keys(): print(t, end = ", ")
– Retrieves the value if the given key print()
exists. for t in D.values(): print(t, end = ", ")
– If not, returns the default value. print()
print(D.get(0, "?"))
print(D.get(15, "?"))

('apple', 1500), ('banana', 1000), (15, 'monkey'),


apple 1500, banana 1000, 15 monkey,
apple, banana, 15,
1500, 1000, monkey,
?
monkey
Type&Run: comprehension

Source code

X = {x : y for x in range(3) for y in range(2)}


print(X)

L = [x * y for x in 'apple' for y in range(3)]


D = {p : q for p in range(2) for q in L if q.startswith('p')}
print(L)
print(D)

Result
{0: 1, 1: 1, 2: 1}
['', 'a', 'aa', '', 'p', 'pp', '', 'p', 'pp', '', 'l', 'll', '', 'e', 'ee']
{0: 'pp', 1: 'pp'}
Type&Run: Dictionary Basics
Source code
D = {'21-123':(1, 2), (2, 1):3.1, 4:True, 2.1:'abc' }
Result
for item in D.items(): ('21-123', (1, 2)), ((2, 1), 3.1), (4, True), (2.1, 'abc'),
print(item , end = ', ') 21-123:(1, 2), (2, 1):3.1, 4:True, 2.1:abc,
print() 21-123, (2, 1), 4, 2.1,
for k, v in D.items(): (1, 2), 3.1, True, abc,
print(k, v, sep = ':', end = ', ') ?
print() True
for k in D.keys():
print(k , end = ', ') {'21-123': (1, 2), (2, 1): 3.1, 4: True, 2.1: 'abc'}
print() {'21-123': (1, 2), (2, 1): 3.1, 4: False, 2.1: 'abc', 0: 45}
for v in D.values(): {(2, 1): 3.1, 4: False, 2.1: 'abc', 0: 45}
print(v , end = ', ') {(2, 1): 3.1, 4: False, 2.1: 'abc'}
print()
print(D.get((1, 2), '?')) abc
print(D.get(4, '?'), '\n') True
{(2, 1): 3.1, 4: False, 2.1: 'abc', 5: True}
D_copy = D.copy() {}
print(D_copy)
D_copy.update({4:False, 0:45}) modify or add
print(D_copy)
D_copy.pop('21-123')
print(D_copy)
D_copy.popitem() # deletes the lastly inserted item
print(D_copy, '\n')

print(D_copy.setdefault(2.1, 'a')) # if the key exists, ignore


print(D_copy.setdefault(5, True)) # if not, create the element
print(D_copy)
D_copy.clear()
print(D_copy)
Type&Run: len, min, max, sum, sorted
Source code Result
T1 = tuple([3, 2, 4, 1, 5]) (3, 2, 4, 1, 5) (1, 2, 3, 4, 5)
T2 = tuple({3, 2, 4, 1, 5}) # set is unordered... 5 1 5 15
print(T1, T2) [1, 2, 3, 4, 5] [5, 4, 3, 2, 1]
print(len(T1), min(T1), max(T1), sum(T1))
print(sorted(T1), sorted(T1, reverse=True), '\n') {1, 2, 3, 4, 5} {1, 2, 3, 4, 5}
5 1 5 15
S1 = set([3, 2, 4, 1, 5]) [1, 2, 3, 4, 5] [5, 4, 3, 2, 1]
S2 = set((3, 2, 4, 1, 5))
print(S1, S2) {1: 1, 5: 25, 0: 0, 3: 9, 7: 49, 9: 81}
print(len(S1), min(S1), max(S1), sum(S1)) 6
print(sorted(S1), sorted(S1, reverse=True), '\n') [0, 1, 3, 5, 7, 9] [9, 7, 5, 3, 1, 0]

D = dict([(1, 1), (5, 25), (0, 0), (3, 9), (7, 49), (9, 81)])
print(D)
print(len(D))
print(sorted(D), sorted(D, reverse=True)) # with the key…
Type&Run: del statement (int, float, bool, string)

Source code Result


v1 = 1 1 2.5 True abc
v2 = 2.5
v3 = True
v4 = 'abc'

print(v1, v2, v3, v4)


del v1
#print(v1) # error
del v2, v3
#print(v2, v3) # error
#del v4[0] # error
Type&Run: del statement (list, tuple)
Source code Result
L = [1, 2.5, True, 'abc'] [1, 2.5, True, 'abc']
T = (1, 2.5, True, 'abc') [2.5, True, 'abc']
[2.5]
print(L)
L_copy = L.copy() [1, 2.5, True, 'abc']
del L[0] [1, 2.5, True, 'abc']
print(L) []
del L[1:]
print(L, '\n') (1, 2.5, True, 'abc')
del L
#print(L) # error

print(L_copy)
for item in L_copy:
del item does not delete
print(L_copy)
for _ in range(len(L_copy)):
del L_copy[0]
#del L_copy[:]
print(L_copy, '\n')

print(T)
#del T[0] # error
del T
#print(T) # error
Type&Run: del statement (set, dictionary)

Source code Result


S = {1, 2.5, True, 'abc'} {1, 2.5, 'abc'}
D = {1: 'a', 2: 'b', (3, 4): 'c'}
{1: 'a', 2: 'b', (3, 4): 'c'}
print(S, '\n') {2: 'b', (3, 4): 'c'}
del S {2: 'b'}
#print(S) # error

print(D)
del D[1]
print(D)
del D[3, 4]
# same as del D[(3, 4)]
print(D)
del D
#print(D) # error
Home Exercise: Using Dictionary for SpMV,
Sparse Matrix and Vector multiplication

• When only a few percent of the matrix is non-zero, we say the matrix is sparse.
– In most real world problems, matrices are sparse.
• The sparse matrix uses specialized matrix storage
– To save the storage, it stores only non-zero elements
• The sparse matrix can be implemented using dictionary.
– The key can be string or tuple as follows:

mat = {} # initializes the dictionary


mat["nr"] = 10 # stores num of rows
mat["nc"] = 10 # stores num of columns
mat[(0,3)] = 100 # mat value at [0,3]
mat[(2,1)] = 50 # mat value at [2,1]
mat.get((0,3), 0) # non-zero element, thus 100
mat.get((1,1), 0) # zero-element, thus 0
Pseudo Code

mat = {}
mat["nr"] = 5 # Replace this with input()
mat["nc"] = 5
for _ in range(10): # produce about 10 nonzero elements
mat[(randint(0,5), randint(0,5))] = randint(1,2)
printMatrix(mat)
vec = []
for i in range(5): # produce the vector
vec[i] = randint(0,3)
print(vec)
vec2 = SpMV(mat, vec)
print(vec2)

2 0 0 1 0
0 0 0 2 0
0 0 0 0 0
0 0 1 1 0
1 0 0 0 0
[0, 1, 3, 3, 1]
[3, 6, 0, 6, 0]
You can Use the Following Functions

def printMatrix(m):
for i in range(m["nr"]):
for j in range(m["nc"]):
print(m.get((i,j),0), end = " ")
print()

def SpDOT(m, i, v):


sum = 0;
for k in range (m["nc"]):
sum += m.get((i,k),0) * v[k]
return sum
Yield and Iterator
yield vs. return
(from GeeksforGeeks)

• The yield statement suspends function’s execution and sends a value back to the caller, but
retains enough state to enable function to resume where it is left off.
• When resumed, the function continues execution immediately after the last yield run.
• The terms “generator” and “driver”
– If the body of a function contains yield, that function is called a generator.
– If a part of the code calls a generator, it is called a driver.
• A typical usage of the generator from the for loop:

def n_seq(n):
# the generator code
num = 0
def generator1(): 0
1 while num < n:
yield 1 in generator
2 yield num * 2
yield 2 6
3 print("in generator")
yield 3 in generator
num += 1
# the driver code 12
for value in generator1(): in generator
for item in n_seq(3):
print(value)
print(item * 3)
Generator returns an Iterator

def n_seq(n): <generator object n_seq at 0x0302BED0>


num = 0 0
while num < n: 1
Error
yield num
num += 1

x = n_seq(2)
print(x)
print(next(x))
print(next(x))
print(next(x))

• The result of the function call n_seq(2) is an iterator.


• An iterator provides a function called next().
• Calls to next() return successive items in the stream.
• When no more data are available, a StopIteration exception is raised.
List is an Iterable, not an Iterator

x = [0, 1, 2] [0, 1, 2]
<list_iterator object at 0x036DA640>
print(x) 0
1
# print(next(x)) # error
# print(next(x)) # error

y = iter(x)
print(y)
print(next(y))
print(next(y))

• Iterable is an object that is capable of returning its members one at a time.


• An iterable is not necessarily an iterator.
• When an iterable object is passed as an argument to the built-in function
iter(), it returns an iterator for that object.
For loop expects an Iterable

for i in [3,4,5]: def generator1(): def n_seq(n):


print(i*2, end = " ") yield 1 num = 0
yield 2 while num < n:
6 8 10 yield 3 yield num
num += 1
# the driver code
for value in generator1(): # the driver code
print(value*2, end = " ") for i in n_seq(5):
print(i*2, end = " ")
2 4 6
0 2 4 6 8

• Review: An iterable is not necessarily an iterator.


• However, an iterator is an iterable, in the sense that, an iterator can come
to the place Python expects an iterable.
• Therefore, an iterator can come to the for loop.
– In fact, to any loop.
Summing an Iterable
• sum(iterable, start)
– iterable: the iterable (e.g., list, tuple, dict, etc.) to sum.
– start (optional): This value is added to the sum. The default value of start is 0 (if omitted)

def n_seq2(n):
num, nums = 0, []
while num < n:
nums.append(num)
num += 1
return nums Needs memory for storing this list

print(sum(n_seq2(11))) 55
Summing an Iterator
• sum(iterable, start)
– iterable: A generator is an iterable, so can come at this place.
– start (optional): This value is added to the sum. The default value of start is 0 (if omitted)

def n_seq(n):
num = 0
while num < n:
yield num
num += 1

print(sum(n_seq(11))) 55

• Does not need the memory to hold the whole list.


• memory efficient!
• Preserve the local context when yielding.
• Does not incur function call/return overhead for each iteration.
Comprehension with () and []
• A comprehension with () produces a generator object, i.e., an iterator.
• A comprehension with [] produces a list, i.e., an iterable.

x = (i for i in range(11))
print(x)
print(next(x))
print(sum(x))
y = [i for i in range(11)]
print(y)
# print(next(y)) produces error
print(sum(y))

<generator object <genexpr> at 0x0385F7D0>


0
55
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
55
Python Comprehensions
• List comprehension
[expression for item in iterable if condition]

• Set comprehension
{expression for item in iterable if condition}

• Dictionary comprehension
{key:value for item in iterable if condition}

• Generator expression
(expression for item in iterable if condition)
Type&Run: various comprehensions

Source code
lComprehension = [i for i in range(10) if i % 2 == 0]
sComprehension = {i for i in range(10) if i % 2 == 1}
dComprehension = {i:2*i for i in range(5) if i % 2 == 0}
gExpression = (i for i in range(10) if i % 2 == 0)

print(lComprehension)
print(sComprehension)
print(dComprehension)
print(gExpression)

Result
[0, 2, 4, 6, 8]
{1, 3, 5, 7, 9}
{0: 0, 2: 4, 4: 8}
<generator object <genexpr> at 0x00000197D78D3190>
Memory Efficiency and Lazy Evaluation of the Generator
• It uses less amount of memory
import sys

print(sys.getsizeof([i for i in range(10)])) 184


print(sys.getsizeof([i for i in range(100)])) 920
print(sys.getsizeof((i for i in range(10)))) 192
print(sys.getsizeof((i for i in range(100)))) 192

• Lazy evaluation
5 seconds passed
import time 0
1
def func(x): 2
time.sleep(1) 3
return x 4
0 1 sec passed
L = [func(x) for x in range(5)] 1 1 sec passed
for item in L: 2 1 sec passed
print(item) 3 1 sec passed
4 1 sec passed
G = (func(x) for x in range(5))
for item in G:
print(item)
Lecture 06

Sets, Tuples, Dictionaries, Yield

The End

You might also like