# CS 1358 Introduction to Programming in Python SC12 ###### tags: `pythonSC` # Definitions and Short Answers - functions 1. Given a for loop: ```python for i in L: print(i) ``` Can L be the following? If so, what does the loop print? If not, why not? - [X] ['a', 'b', 'c'] - [X] ('a', 'b', 'c') - [X] 'abc' - [X] {'a', 'b', 'c'} - [X] {'a': 100, 'b': 200, 'c': 300} - [ ] 0xabcd - [X] range(3) - [ ] 23+4j 2. Given an iterable data structure L a. How do you obtain an iterator r of L? > r = iter(L) b. Once you have an iterator r, what can you do to get the next value? > next\(r\) c. What happens when you call next(r) but your iterator r has finished iterating over all values of L? > StopIteration d. Is there a limit to the number of iterators that you can create on the same iterable? > No 3. Assume you have ```python= D = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] r = iter(D) L = [next(r) for i in range(3)] s = iter(D) M = [next(s) for i in range(2)] ``` after executing these five lines a. What is the value of L? ``` ['Sun', 'Mon', 'Tue'] ``` b. What is the value of M? ``` ['Sun', 'Mon'] ``` c. What is the value of D? ``` ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] ``` 4. Recall the Vector class from the previous lecture ```python= import operator as op class Vector: def __init__(self, *v): self._v = list(v) # covert tuple to list def __repr__(self): return __class__.__name__+repr(tuple(self._v)) ``` Suppose a class defines an \_\_iter__() special method, and v is an instance of Vector. a. How does Python intend that v's \_\_iter__() special method be invoked by the programmer? Hint: not v.\_\_iter__() > modify \_\_getitem__() b. What kind of object should the \_\_iter__() method return? > custom iterator class c. What is one simple way to implement Vector's \_\_iter__() method, given that the iterator for Vector would essentially be the same as the iterator for the list self._v ? > return list_iterator(self) 5. An alternative to part 4.(c) is to define a class for VectorIterator, and Vector's \_\_iter__() method would instantiate and return it. The code is as follows: ```python= class Vector: def __iter__(self): return Vector_Iterator(self): class VectorIterator: def __init__(self, vec): self._vec = vec self._i = 0 def __next__(self): if self._i >= len(self._vec): raise StopIteration val = self._vec[self._i] self._i += 1 return val ``` a. In VectorIterator's constructor, what is the purpose of initializing _i = 0? > to initialize the position b. Why does VectorIterator's constructor need to set its _vec attribute to the iterable? Why isn't it enough to just keep track of its position _i? > 這樣他next()的時候 就沒有辦法回傳資料了阿 c. How does Python intend that the \_\_next__() method of a VectorIterator instance vi be invoked? Hint: not vi.\_\_next__() > next(vi) d. How does \_\_next__() special method indicate that it has finished iterating all elements? > When i larger than len(self._vec) raise StopIteration 6. Assume Vector is iterable, rewrite the following for-loop using a while loop and explicit iter() instantiation, next(), and catching StopIteration exception: ```python= v = Vector(7, 1, 4, 3, 9, 6, 5) i = iter(v) while True: try: print(next(i), end = '') except StopIteration: break ``` 7. Can any iterable object v be passed as arguments to - [x] list(v) - [x] max(v) 8. For the Blackjack game example, Card is declared as a class: ```python= class Class: ACE, JACK, QUEEN, KING = 'A', 'J', 'Q', 'K' FACES = (ACE,2,3,4,5,6,7,8,9,10, JACK, QUEEN, KING) SUITS = tuple(map(chr, (9824, 9827, 9829, 9830))) SPADE, CLUB, HEART, DIAMOND = SUITS # ♠ ♣ ♥ ♦ def __init__(self, suit, face):
 self._suit = suit self._face = face def __int__(self): if self._face in {Card.JACK,Card.QUEEN,Card.KING}: return 10 return 1 if self._face == Card.ACE else self._face def __str__(self): return self._suit + str(self._face) def __repr__(self): return __class__.__name__ + \ repr((self._suit, self._face)) ``` a. Why is it a good practice to declare class attributes such as SPADE, CLUB, HEART, and DIAMOND even though Python3 handles unicode character literals such as '♠' '♣' '♥' '♦'. > It can't be an identifer. b. What is the purpose of special method \_\_int__()? > For returning the value of the card. c. Why declare a \_\_str__() special method even though \_\_repr__() also exists and can make a string that represents the card? > 為了支援str()這個built-in function d. Is Card class iterable? Should it be iterable? > No, it didn't define \_\_iter()__ e. Is Card class for instantiating iterators? > No 9. Continuing with the BlackJack example, a separate class named Deck is also declared. ```python= class Deck: def __init__(self): self._deck = [Card(suit, face) \ for suit in Card.SUITS for face in Card.FACES] def shuffle(self): import random random.shuffle(self._deck) def __iter__(self): return iter(self._deck) ``` a. Is Deck an iterable? If so, is it required to implement the \_\_getitem__() special method? > Yes, No b. Explain how the Deck class is able to create iterators by simply returning iter(self._deck) from its \_\_iter__() special method. Explain why this works. > ._deck is a list, list is iterable. 10. In Single-player BlackJack, ```python= def BlackJack(): D = Deck() D.shuffle() total = 0 it = iter(D) while True: c = next(it) total += int(c) print(f'your card: {c}, total = {total}.', end='') if total > 21: print(f'you lose! total = {total}') break if total == 21: print(f'you win! total = 21') break ans = input('More cards? [y/n] ') if ans not in 'Yy': c = next(it) # draw one more to test print(f'next card {c}. You ' +\ ('win' if total + c > 21 else 'lose')) break ``` a. What kind of object is it as created on line 6? > The iterator of Deck (list_iterator) b. What kind of object is returned by a call to next(it) on line 7 or 18? > Card c. Why doesn't this program have to handle the case where the iterator raises StopIteration exception when the deck is empty? > Use the list_iterator which help tp handle thx exceptioin 11. Is the following a function or a generator? - [x] a ```python def X(z): for i in range(20): yield i ``` - [ ] b ```python def Y(z): for i in range(20): return i ``` - [x] c ```python def K(z): for i in range(20): yield i return -1 ``` 12. if fib() is a generator for Fibonacci numbers, what is the syntax for ```python= g = fib() # instantiate generator init_num = next(g) print('initial number = ', init_num) for i in range(10): num = next(g) print(num) ``` 13. Assume g = fib() is a generator for Fibonacci numbers, and r = iter(deck) is an iterator where deck is an instance of iterable class Deck Which of the following are allowed? - [x] a. list\(r\) - [x] b. list(g) - [x] c. list(fib()) - [x] d. list(deck) - [x] e. [i for i in r] - [x] f. [i for i in g] - [x] g. [i for i in fib()] - [x] h. [i for i in iter(deck)] - [x] i. next\(r\) - [x] j. next(g) - [ ] k. x, y, z = deck - [ ] l. x, y, z = fib() - [ ] m. x, y, z = g - [ ] n. x, y, z = r