CS61A Lab 6

更好的阅读体验

Lab 6: Object-Oriented Programming lab06.zip

What Would Python Do?

These questions use inheritance. For an overview of inheritance, see the inheritance portion of Composing Programs.

Q1: WWPD: Classy Cars

Below is the definition of a Car class that we will be using in the following WWPD questions.

Note: The Car class definition can also be found in car.py.

class Car:
    num_wheels = 4
    gas = 30
    headlights = 2
    size = 'Tiny'

    def __init__(self, make, model):
        self.make = make
        self.model = model
        self.color = 'No color yet. You need to paint me.'
        self.wheels = Car.num_wheels
        self.gas = Car.gas

    def paint(self, color):
        self.color = color
        return self.make + ' ' + self.model + ' is now ' + color

    def drive(self):
        if self.wheels < Car.num_wheels or self.gas <= 0:
            return 'Cannot drive!'
        self.gas -= 10
        return self.make + ' ' + self.model + ' goes vroom!'

    def pop_tire(self):
        if self.wheels > 0:
            self.wheels -= 1

    def fill_gas(self):
        self.gas += 20
        return 'Gas level: ' + str(self.gas)

For the later unlocking questions, we will be referencing the MonsterTruck class below.

Note: The MonsterTruck class definition can also be found in car.py.

 class MonsterTruck(Car):
     size = 'Monster'

     def rev(self):
         print('Vroom! This Monster Truck is huge!')

     def drive(self):
         self.rev()
         return super().drive()

You can find the unlocking questions below.

Use Ok to test your knowledge with the following “What Would Python Display?” questions:

python3 ok -q wwpd-car -u✂️

Important: For all WWPD questions, type Function if you believe the answer is <function...>, Error if it errors, and Nothing if nothing is displayed.

>>> deneros_car = Car('Tesla', 'Model S')
>>> deneros_car.model

______
>>> deneros_car.gas = 10
>>> deneros_car.drive()

______
>>> deneros_car.drive()

______
>>> deneros_car.fill_gas()

______
>>> deneros_car.gas

______
>>> Car.gas

______
>>> deneros_car = Car('Tesla', 'Model S')
>>> deneros_car.wheels = 2
>>> deneros_car.wheels

______
>>> Car.num_wheels

______
>>> deneros_car.drive()

______
>>> Car.drive()

______
>>> Car.drive(deneros_car)

______
>>> deneros_car = MonsterTruck('Monster', 'Batmobile')
>>> deneros_car.drive()

______
>>> Car.drive(deneros_car)

______
>>> MonsterTruck.drive(deneros_car)

______
>>> Car.rev(deneros_car)

______

What would Python display? If you get stuck, try it out in the Python
interpreter!

>>> from car import *
>>> deneros_car = Car('Tesla', 'Model S')
>>> deneros_car.model
? Model S
-- Not quite. Try again! --

? 'Model S'
-- OK! --

>>> deneros_car.gas = 10
>>> deneros_car.drive()
? Tesla Model S goes vroom!
-- Not quite. Try again! --

? 'Tesla Model S goes vroom!'
-- OK! --

>>> deneros_car.drive()
? 'Cannot drive'
-- Not quite. Try again! --

? 'Cannot drive!'
-- OK! --

>>> deneros_car.fill_gas()
? 'Gas level: 20'
-- OK! --

>>> deneros_car.gas
? 20
-- OK! --

>>> Car.gas
? 30
-- OK! --

---------------------------------------------------------------------
Car > Suite 1 > Case 2
(cases remaining: 2)

What would Python display? If you get stuck, try it out in the Python
interpreter!

>>> from car import *
>>> deneros_car = Car('Tesla', 'Model S')
>>> deneros_car.wheels = 2
>>> deneros_car.wheels
? 2
-- OK! --

>>> Car.num_wheels
? 4
-- OK! --

>>> deneros_car.drive() # Type Error if an error occurs and Nothing if nothing is displayed
? 'Cannot drive'
-- Not quite. Try again! --

? 'Cannot drive!'
-- OK! --

>>> Car.drive() # Type Error if an error occurs and Nothing if nothing is displayed
? Nothing
-- Not quite. Try again! --

? Error
-- OK! --

>>> Car.drive(deneros_car) # Type Error if an error occurs and Nothing if nothing is displayed
? 'Cannot drive!'
-- OK! --

---------------------------------------------------------------------
Car > Suite 1 > Case 3
(cases remaining: 1)

What would Python display? If you get stuck, try it out in the Python
interpreter!

>>> from car import *
>>> deneros_car = MonsterTruck('Monster', 'Batmobile')
>>> deneros_car.drive() # Type Error if an error occurs and Nothing if nothing is displayed
(line 1)? Vroom! This Monster Truck is huge!
(line 2)? 'Monster Batmobile goes vroom!'
-- OK! --

>>> Car.drive(deneros_car) # Type Error if an error occurs and Nothing if nothing is displayed
? 'Monster Batmobile goes vroom!'
-- OK! --

>>> MonsterTruck.drive(deneros_car) # Type Error if an error occurs and Nothing if nothing is displayed
(line 1)? Vroom! This Monster Truck is huge!
(line 2)? 'Monster Batmobile goes vroom!'
-- OK! --

>>> Car.rev(deneros_car) # Type Error if an error occurs and Nothing if nothing is displayed
? Vroom! This Monster Truck is huge!
-- Not quite. Try again! --

? Error
-- OK! --

---------------------------------------------------------------------
OK! All cases for Car unlocked.

Parsons Problems

To work on these problems, open the Parsons editor:

python3 parsons

Q2: Cool Cats

The Cat class models a cat: you can find the implementation below. Now, you will implement NoisyCat; NoisyCats are very similar to Cats, but talks twice as much. However, in exchange for such great powers, it gives up one of its initial lives.

Use superclass methods wherever possible.

class Cat:
    def __init__(self, name, owner, lives=9):
        self.is_alive = True
        self.name = name
        self.owner = owner
        self.lives = lives

    def talk(self):
        return self.name + ' says meow!'

class NoisyCat(Cat):
    """
    >>> my_cat = NoisyCat("Furball", "James")
    >>> my_cat.name
    'Furball'
    >>> my_cat.is_alive
    True
    >>> my_cat.lives
    8
    >>> my_cat.talk()
    'Furball says meow! Furball says meow!'
    >>> friend_cat = NoisyCat("Tabby", "James", 2)
    >>> friend_cat.talk()
    'Tabby says meow! Tabby says meow!'
    >>> friend_cat.lives
    1
    """
    def __init__(self, name, owner, lives=9):
        Cat.__init__(self, name, owner, lives)
        self.lives -= 1
        
    def talk(self):
        words = Cat.talk(self)
        words = words + ' ' + words
        return words

Coding Practice

Q3: Cat Adoption

So far, you’ve implemented the NoisyCat based off of the Cat class. However, you now want to be able to create lots of different Cats!

Build on the Cat class from the earlier problem by adding a class method called adopt_a_cat. This class method allows you to create Cats that can then be adopted.

Specifically, adopt_a_cat should return a new instance of a Cat whose owner is owner.

This Cat instance’s name and number of lives depends on the owner. Its name should be chosen from cat_names (provided in the skeleton code), and should correspond to the name at the index len(owner) % (modulo) the number of possible cat names. Its number of lives should be equal to len(owner) + the length of the chosen name.

class Cat:
    def __init__(self, name, owner, lives=9):
        self.is_alive = True
        self.name = name
        self.owner = owner
        self.lives = lives

    def talk(self):
        return self.name + ' says meow!'

    @classmethod
    def adopt_a_cat(cls, owner):
        """
        Returns a new instance of a Cat.

        This instance's owner is the given owner.
        Its name and its number of lives is chosen programatically
        based on the spec's noted behavior.

        >>> cat1 = Cat.adopt_a_cat("Ifeoma")
        >>> isinstance(cat1, Cat)
        True
        >>> cat1.owner
        'Ifeoma'
        >>> cat1.name
        'Felix'
        >>> cat1.lives
        11
        >>> cat2 = Cat.adopt_a_cat("Ay")
        >>> cat2.owner
        'Ay'
        >>> cat2.name
        'Grumpy'
        >>> cat2.lives
        8
        """
        cat_names = ["Felix", "Bugs", "Grumpy"]
        "*** YOUR CODE HERE ***"
        cat_name = cat_names[len(owner) % 3]
        lives = len(owner) + len(cat_name)
        return cls(cat_name, owner, lives)

Use Ok to test your code:

python3 ok -q Cat.adopt_a_cat✂️

Accounts

Let’s say we’d like to model a bank account that can handle interactions such as depositing funds or gaining interest on current funds. In the following questions, we will be building off of the Account class. Here’s our current definition of the class:

class Account:
    """An account has a balance and a holder.
    >>> a = Account('John')
    >>> a.deposit(10)
    10
    >>> a.balance
    10
    >>> a.interest
    0.02
    >>> a.time_to_retire(10.25) # 10 -> 10.2 -> 10.404
    2
    >>> a.balance               # balance should not change
    10
    >>> a.time_to_retire(11)    # 10 -> 10.2 -> ... -> 11.040808032
    5
    >>> a.time_to_retire(100)
    117
    """
    max_withdrawal = 10
    interest = 0.02

    def __init__(self, account_holder):
        self.balance = 0
        self.holder = account_holder

    def deposit(self, amount):
        self.balance = self.balance + amount
        return self.balance

    def withdraw(self, amount):
        if amount > self.balance:
            return "Insufficient funds"
        if amount > self.max_withdrawal:
            return "Can't withdraw that amount"
        self.balance = self.balance - amount
        return self.balance

Q4: Retirement

Add a time_to_retire method to the Account class. This method takes in an amount and returns how many years the holder would need to wait in order for the current balance to grow to at least amount, assuming that the bank adds balance times the interest rate to the total balance at the end of every year.

    def time_to_retire(self, amount):
        """Return the number of years until balance would grow to amount."""
        assert self.balance > 0 and amount > 0 and self.interest > 0
        "*** YOUR CODE HERE ***"
        cnt = 0
        deposit = self.balance * ((1 + self.interest) ** cnt)
        while deposit < amount:
            cnt = cnt + 1
            deposit = self.balance * ((1 + self.interest) ** cnt)
        return cnt

Use Ok to test your code:

python3 ok -q Account✂️

Q5: FreeChecking

Implement the FreeChecking class, which is like the Account class from lecture except that it charges a withdraw fee after 2 withdrawals. If a withdrawal is unsuccessful, it still counts towards the number of free withdrawals remaining, but no fee for the withdrawal will be charged.

Hint: Don’t forget that FreeChecking inherits from Account! Check the Inheritance section in Topics for a refresher.

class FreeChecking(Account):
    """A bank account that charges for withdrawals, but the first two are free!
    >>> ch = FreeChecking('Jack')
    >>> ch.balance = 20
    >>> ch.withdraw(100)  # First one's free
    'Insufficient funds'
    >>> ch.withdraw(3)    # And the second
    17
    >>> ch.balance
    17
    >>> ch.withdraw(3)    # Ok, two free withdrawals is enough
    13
    >>> ch.withdraw(3)
    9
    >>> ch2 = FreeChecking('John')
    >>> ch2.balance = 10
    >>> ch2.withdraw(3) # No fee
    7
    >>> ch.withdraw(3)  # ch still charges a fee
    5
    >>> ch.withdraw(5)  # Not enough to cover fee + withdraw
    'Insufficient funds'
    """
    withdraw_fee = 1
    free_withdrawals = 2

    "*** YOUR CODE HERE ***"
    def __init__(self, Account):
        Account.__init__(self)

    def withdraw(self, amount):
        if amount + self.withdraw_fee > self.balance:
            return "Insufficient funds"
        if amount > self.max_withdrawal:
            return "Can't withdraw that amount"
        
        
        if self.free_withdrawals > 0: 
            self.free_withdrawals -= 1
        
        self.balance = self.balance - amount
        if self.free_withdrawals <= 0:
            self.balance = self.balance - self.withdraw_fee
        
        return self.balance

Use Ok to test your code:

python3 ok -q FreeChecking✂️

Submit

Make sure to submit this assignment by running:

python3 ok --submit
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值