Try   HackMD

CS 1358 Introduction to Programming in Python SC12

tags: pythonSC

Definitions and Short Answers - functions

  1. Given a for loop:

    ​​​​for i in L:
    ​​​​      print(i)
    

    Can L be the following? If so, what does the loop print? If not, why not?

    • ['a', 'b', 'c']
    • ('a', 'b', 'c')
    • 'abc'
    • {'a', 'b', 'c'}
    • {'a': 100, 'b': 200, 'c': 300}
    • 0xabcd
    • 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® 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

    ​​​​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

    ​​​​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.© is to define a class for VectorIterator, and Vector's __iter__() method would instantiate and return it. The code is as follows:

    ​​​​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:

    ​​​​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

    • list(v)
    • max(v)
  8. For the Blackjack game example, Card is declared as a class:

    ​​​​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.

    ​​​​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,

    ​​​​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?

    • a
    ​​​​def X(z):
    ​​​​    for i in range(20):
    ​​​​        yield i
    
    • b
    ​​​​def Y(z):
    ​​​​    for i in range(20):
    ​​​​        return i
    
    • c
    ​​​​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

    ​​​​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?

    • a. list(r)
    • b. list(g)
    • c. list(fib())
    • d. list(deck)
    • e. [i for i in r]
    • f. [i for i in g]
    • g. [i for i in fib()]
    • h. [i for i in iter(deck)]
    • i. next(r)
    • j. next(g)
    • k. x, y, z = deck
    • l. x, y, z = fib()
    • m. x, y, z = g
    • n. x, y, z = r