当前位置: 首页 > article >正文

【CS61A 2024秋】Python入门课,全过程记录P5(Week8 Inheritance开始,更新于2025/2/3)

文章目录

  • 关于
  • 基本介绍👋
  • 新的问题
  • 更好的解决方案
  • Week8
    • Mon Inheritance
      • 阅读材料
      • Lab 06: Object-Oriented Programming
        • Q1: Bank Account
        • Q2: Email
        • Q3: Mint
    • Wed Representation
      • 阅读材料
      • Disc 07: OOP
        • Q1: Draw
        • Q2: Keyboard
        • Q3: Bear
    • Fri Composition
      • 阅读材料
      • HW 06: Object-Oriented Programming, Linked Lists
        • Q1: Mid-Semester Feedback
        • Q2: Vending Machine
        • Q3: Store Digits
        • Q4: Mutable Mapping
        • Q5: Two List
  • Week9
    • Mon Efficiency
      • 阅读材料
      • Lab 07: Linked Lists, Inheritance
        • Q1: WWPD: Inheritance ABCs
        • Q2: Retirement

关于

个人博客,里面偶尔更新,最近比较忙。发一些总结的帖子和思考。

江湖有缘相见🤝。如果读者想和我交个朋友可以加我好友(见主页or个人博客),共同学习。笔者是学生,课业还是比较繁重的,可能回复不及时。笔者也正在四处寻找一些可以兼职锻炼知识并且补贴一些生活的工作,如果读者需要一些详细的辅导,或者帮助完成一些简易的lab也可以找我,笔者还是学生,自以为才学有限,也没有高价的理由📖。

基本介绍👋

CS61A是加州大学伯克利分校(UC Berkeley)计算机科学专业的入门课程,全名为Structure and Interpretation of Computer Programs。

这是入门的Python课程,因此这篇博客会默认读者没有很多的编程背景,讲的东西会比较基础,有编程经验的读者可以快速浏览。

首先贴上课程网址。
CS61A课程主页

新的问题

在这里插入图片描述
可以发现,cs61a归档了,而这个网站是需要Berkeley账号的,还是没法登录。这时候笔者决定使用档案馆网站,去翻网页的归档了。虽然有点难受,但是还能用orz。

对了,textbook是可以直接访问的,在这里

更好的解决方案

我在GitHub上找到了cs61a 2024 fall的归档,这里给出连接link

Week8

Mon Inheritance

阅读材料

Ants里面已经写了很多类了,这里才开始具体讲面向对象编程orz。

Lab 06: Object-Oriented Programming

关键是要搞清楚实例属性,类属性的区别。前者修改只会影响当前实例,后者会影响当前类的全部实例。

Q1: Bank Account

这题注意交易失败也要记录下来。

class Transaction:
    def __init__(self, id, before, after):
        self.id = id
        self.before = before
        self.after = after

    def changed(self):
        """Return whether the transaction resulted in a changed balance."""
        "*** YOUR CODE HERE ***"
        return self.before != self.after

    def report(self):
        """Return a string describing the transaction.

        >>> Transaction(3, 20, 10).report()
        '3: decreased 20->10'
        >>> Transaction(4, 20, 50).report()
        '4: increased 20->50'
        >>> Transaction(5, 50, 50).report()
        '5: no change'
        """
        msg = 'no change'
        if self.changed():
            "*** YOUR CODE HERE ***"
            if self.after > self.before:
                msg = f'increased {self.before}->{self.after}'
            else:
                msg = f'decreased {self.before}->{self.after}'
        return str(self.id) + ': ' + msg

class BankAccount:
    """A bank account that tracks its transaction history.

    >>> a = BankAccount('Eric')
    >>> a.deposit(100)    # Transaction 0 for a
    100
    >>> b = BankAccount('Erica')
    >>> a.withdraw(30)    # Transaction 1 for a
    70
    >>> a.deposit(10)     # Transaction 2 for a
    80
    >>> b.deposit(50)     # Transaction 0 for b
    50
    >>> b.withdraw(10)    # Transaction 1 for b
    40
    >>> a.withdraw(100)   # Transaction 3 for a
    'Insufficient funds'
    >>> len(a.transactions)
    4
    >>> len([t for t in a.transactions if t.changed()])
    3
    >>> for t in a.transactions:
    ...     print(t.report())
    0: increased 0->100
    1: decreased 100->70
    2: increased 70->80
    3: no change
    >>> b.withdraw(100)   # Transaction 2 for b
    'Insufficient funds'
    >>> b.withdraw(30)    # Transaction 3 for b
    10
    >>> for t in b.transactions:
    ...     print(t.report())
    0: increased 0->50
    1: decreased 50->40
    2: no change
    3: decreased 40->10
    """

    # *** YOU NEED TO MAKE CHANGES IN SEVERAL PLACES IN THIS CLASS ***

    def __init__(self, account_holder):
        self.balance = 0
        self.holder = account_holder
        self.id = 0
        self.transactions = []

    def deposit(self, amount):
        """Increase the account balance by amount, add the deposit
        to the transaction history, and return the new balance.
        """
        self.transactions.append(Transaction(self.id, self.balance, self.balance + amount))
        self.id += 1
        self.balance = self.balance + amount
        return self.balance

    def withdraw(self, amount):
        """Decrease the account balance by amount, add the withdraw
        to the transaction history, and return the new balance.
        """
        if amount > self.balance:
            self.transactions.append(Transaction(self.id, self.balance, self.balance))
            self.id += 1
            return 'Insufficient funds'
        self.transactions.append(Transaction(self.id, self.balance, self.balance - amount))
        self.id += 1
        self.balance = self.balance - amount
        return self.balance
Q2: Email

填完邮件类。注意一下即可。

class Email:
    """An email has the following instance attributes:

        msg (str): the contents of the message
        sender (Client): the client that sent the email
        recipient_name (str): the name of the recipient (another client)
    """
    def __init__(self, msg, sender, recipient_name):
        self.msg = msg
        self.sender = sender
        self.recipient_name = recipient_name

class Server:
    """Each Server has one instance attribute called clients that is a
    dictionary from client names to client objects.
    """
    def __init__(self):
        self.clients = {}

    def send(self, email):
        """Append the email to the inbox of the client it is addressed to.
            email is an instance of the Email class.
        """
        self.clients[email.recipient_name].inbox.append(email)

    def register_client(self, client):
        """Add a client to the clients mapping (which is a 
        dictionary from client names to client instances).
            client is an instance of the Client class.
        """
        self.clients[client.name] = client

class Client:
    """A client has a server, a name (str), and an inbox (list).

    >>> s = Server()
    >>> a = Client(s, 'Alice')
    >>> b = Client(s, 'Bob')
    >>> a.compose('Hello, World!', 'Bob')
    >>> b.inbox[0].msg
    'Hello, World!'
    >>> a.compose('CS 61A Rocks!', 'Bob')
    >>> len(b.inbox)
    2
    >>> b.inbox[1].msg
    'CS 61A Rocks!'
    >>> b.inbox[1].sender.name
    'Alice'
    """
    def __init__(self, server, name):
        self.inbox = []
        self.server = server
        self.name = name
        server.register_client(self)

    def compose(self, message, recipient_name):
        """Send an email with the given message to the recipient."""
        email = Email(message, self, recipient_name)
        self.server.send(email)
Q3: Mint

可以通过类名直接获取类属性。

class Mint:
    """A mint creates coins by stamping on years.

    The update method sets the mint's stamp to Mint.present_year.

    >>> mint = Mint()
    >>> mint.year
    2024
    >>> dime = mint.create(Dime)
    >>> dime.year
    2024
    >>> Mint.present_year = 2104  # Time passes
    >>> nickel = mint.create(Nickel)
    >>> nickel.year     # The mint has not updated its stamp yet
    2024
    >>> nickel.worth()  # 5 cents + (80 - 50 years)
    35
    >>> mint.update()   # The mint's year is updated to 2104
    >>> Mint.present_year = 2179     # More time passes
    >>> mint.create(Dime).worth()    # 10 cents + (75 - 50 years)
    35
    >>> Mint().create(Dime).worth()  # A new mint has the current year
    10
    >>> dime.worth()     # 10 cents + (155 - 50 years)
    115
    >>> Dime.cents = 20  # Upgrade all dimes!
    >>> dime.worth()     # 20 cents + (155 - 50 years)
    125
    """
    present_year = 2024

    def __init__(self):
        self.update()

    def create(self, coin):
        "*** YOUR CODE HERE ***"
        return coin(self.year)

    def update(self):
        "*** YOUR CODE HERE ***"
        self.year = self.present_year

class Coin:
    cents = None # will be provided by subclasses, but not by Coin itself

    def __init__(self, year):
        self.year = year

    def worth(self):
        "*** YOUR CODE HERE ***"
        return self.cents + max(Mint.present_year - self.year - 50, 0)

class Nickel(Coin):
    cents = 5

class Dime(Coin):
    cents = 10

Wed Representation

阅读材料

主要讲了一些例子。略。

Disc 07: OOP

Q1: Draw

这里的pop要注意,必须从大到小pop,因为pop前面的数会影响后面的数的下标。注意后面还需要翻转回来,保持在原来序列的顺序。

def draw(hand, positions):
    """Remove and return the items at positions from hand.

    >>> hand = ['A', 'K', 'Q', 'J', 10, 9]
    >>> draw(hand, [2, 1, 4])
    ['K', 'Q', 10]
    >>> hand
    ['A', 'J', 9]
    """
    return list(reversed( [hand.pop(i) for i in reversed(sorted(positions))] ))

Q2: Keyboard

根据文档测试很容易写出,Button的press要返回self,文档测试里有.press.press。

LOWERCASE_LETTERS = 'abcdefghijklmnopqrstuvwxyz'

class CapsLock:
    def __init__(self):
        self.pressed = 0

    def press(self):
        self.pressed += 1

class Button:
    """A button on a keyboard.

    >>> f = lambda c: print(c, end='')  # The end='' argument avoids going to a new line
    >>> k, e, y = Button('k', f), Button('e', f), Button('y', f)
    >>> s = e.press().press().press()
    eee
    >>> caps = Button.caps_lock
    >>> t = [x.press() for x in [k, e, y, caps, e, e, k, caps, e, y, e, caps, y, e, e]]
    keyEEKeyeYEE
    >>> u = Button('a', print).press().press().press()
    A
    A
    A
    """
    caps_lock = CapsLock()

    def __init__(self, letter, output):
        assert letter in LOWERCASE_LETTERS
        self.letter = letter
        self.output = output
        self.pressed = 0

    def press(self):
        """Call output on letter (maybe uppercased), then return the button that was pressed."""
        self.pressed += 1
        "*** YOUR CODE HERE ***"
        if self.caps_lock.pressed % 2 == 1:
            self.output(self.letter.upper())
        else:
            self.output(self.letter)
        return self
Q3: Bear

根据文档测试写即可。


class SleepyBear(Bear):
    """A bear with closed eyes.

    >>> SleepyBear().print()
    ? -o-?
    """
    "*** YOUR CODE HERE ***"
    def next_eye(self):
        return Eye(True)

class WinkingBear(Bear):
    """A bear whose left eye is different from its right eye.

    >>> WinkingBear().print()
    ? -o0?
    """
    def __init__(self):
        "*** YOUR CODE HERE ***"
        self.cur = 0
        self.nose_and_mouth = 'o'

    def next_eye(self):
        "*** YOUR CODE HERE ***"
        if self.cur == 0:
            self.cur += 1
            return Eye(True)
        else:
            self.cur += 1
            return Eye(False)

Fri Composition

阅读材料

讲解链表,链表不管用什么语言都是非常的繁琐,据说Rust的链表更是地狱级难度。

HW 06: Object-Oriented Programming, Linked Lists

Q1: Mid-Semester Feedback

略。期中评价。

Q2: Vending Machine

售货机,比较简单。

class VendingMachine:
    """A vending machine that vends some product for some price.

    >>> v = VendingMachine('candy', 10)
    >>> v.vend()
    'Nothing left to vend. Please restock.'
    >>> v.add_funds(15)
    'Nothing left to vend. Please restock. Here is your $15.'
    >>> v.restock(2)
    'Current candy stock: 2'
    >>> v.vend()
    'Please add $10 more funds.'
    >>> v.add_funds(7)
    'Current balance: $7'
    >>> v.vend()
    'Please add $3 more funds.'
    >>> v.add_funds(5)
    'Current balance: $12'
    >>> v.vend()
    'Here is your candy and $2 change.'
    >>> v.add_funds(10)
    'Current balance: $10'
    >>> v.vend()
    'Here is your candy.'
    >>> v.add_funds(15)
    'Nothing left to vend. Please restock. Here is your $15.'

    >>> w = VendingMachine('soda', 2)
    >>> w.restock(3)
    'Current soda stock: 3'
    >>> w.restock(3)
    'Current soda stock: 6'
    >>> w.add_funds(2)
    'Current balance: $2'
    >>> w.vend()
    'Here is your soda.'
    """
    def __init__(self, product, price):
        """Set the product and its price, as well as other instance attributes."""
        "*** YOUR CODE HERE ***"
        self.product = product
        self.price = price
        self.balance = 0
        self.stock = 0

    def restock(self, n):
        """Add n to the stock and return a message about the updated stock level.

        E.g., Current candy stock: 3
        """
        "*** YOUR CODE HERE ***"
        self.stock += n
        return f'Current {self.product} stock: {self.stock}'

    def add_funds(self, n):
        """If the machine is out of stock, return a message informing the user to restock
        (and return their n dollars).

        E.g., Nothing left to vend. Please restock. Here is your $4.

        Otherwise, add n to the balance and return a message about the updated balance.

        E.g., Current balance: $4
        """
        "*** YOUR CODE HERE ***"
        self.balance += n
        if self.stock == 0:
            cur = self.balance
            self.balance = 0
            return f'Nothing left to vend. Please restock. Here is your ${cur}.'
        return f'Current balance: ${self.balance}'

    def vend(self):
        """Dispense the product if there is sufficient stock and funds and
        return a message. Update the stock and balance accordingly.

        E.g., Here is your candy and $2 change.

        If not, return a message suggesting how to correct the problem.

        E.g., Nothing left to vend. Please restock.
              Please add $3 more funds.
        """
        "*** YOUR CODE HERE ***"
        if self.stock == 0:
            return f'Nothing left to vend. Please restock.'
        if self.balance < self.price:
            return f'Please add ${self.price - self.balance} more funds.'
        if self.balance > self.price:
            change = self.balance - self.price
            self.stock -= 1
            self.balance = 0
            return f'Here is your {self.product} and ${change} change.'
        self.stock -= 1
        self.balance = 0
        return f'Here is your {self.product}.'
Q3: Store Digits

使用链表存储数字。

def store_digits(n):
    """Stores the digits of a positive number n in a linked list.

    >>> s = store_digits(1)
    >>> s
    Link(1)
    >>> store_digits(2345)
    Link(2, Link(3, Link(4, Link(5))))
    >>> store_digits(876)
    Link(8, Link(7, Link(6)))
    >>> store_digits(2450)
    Link(2, Link(4, Link(5, Link(0))))
    >>> store_digits(20105)
    Link(2, Link(0, Link(1, Link(0, Link(5)))))
    >>> # a check for restricted functions
    >>> import inspect, re
    >>> cleaned = re.sub(r"#.*\\n", '', re.sub(r'"{3}[\s\S]*?"{3}', '', inspect.getsource(store_digits)))
    >>> print("Do not use str or reversed!") if any([r in cleaned for r in ["str", "reversed"]]) else None
    """
    "*** YOUR CODE HERE ***"
    def f(n, link):
        if n < 10:
            return Link(n, link)
        return f(n // 10, Link(n % 10, link))
    return f(n, Link.empty)
Q4: Mutable Mapping

设计一个map,映射链表内全部的元素。

def deep_map_mut(func, s):
    """Mutates a deep link s by replacing each item found with the
    result of calling func on the item. Does NOT create new Links (so
    no use of Link's constructor).

    Does not return the modified Link object.

    >>> link1 = Link(3, Link(Link(4), Link(5, Link(6))))
    >>> print(link1)
    <3 <4> 5 6>
    >>> # Disallow the use of making new Links before calling deep_map_mut
    >>> Link.__init__, hold = lambda *args: print("Do not create any new Links."), Link.__init__
    >>> try:
    ...     deep_map_mut(lambda x: x * x, link1)
    ... finally:
    ...     Link.__init__ = hold
    >>> print(link1)
    <9 <16> 25 36>
    """
    "*** YOUR CODE HERE ***"
   
    if isinstance(s.first, Link):
        deep_map_mut(func, s.first)
    else:
        s.first = func(s.first)
    if isinstance(s.rest, Link):
        deep_map_mut(func, s.rest)

Q5: Two List

直接暴力递归。

def two_list(vals, counts):
    """
    Returns a linked list according to the two lists that were passed in. Assume
    vals and counts are the same size. Elements in vals represent the value, and the
    corresponding element in counts represents the number of this value desired in the
    final linked list. Assume all elements in counts are greater than 0. Assume both
    lists have at least one element.
    >>> a = [1, 3]
    >>> b = [1, 1]
    >>> c = two_list(a, b)
    >>> c
    Link(1, Link(3))
    >>> a = [1, 3, 2]
    >>> b = [2, 2, 1]
    >>> c = two_list(a, b)
    >>> c
    Link(1, Link(1, Link(3, Link(3, Link(2)))))
    """
    "*** YOUR CODE HERE ***"
    if counts:
        if counts[0] > 1:
            counts[0] -= 1
            return Link(vals[0], two_list(vals, counts))
        else:
            return Link(vals[0], two_list(vals[1:], counts[1:]))
    else:
        return Link.empty

Week9

Mon Efficiency

阅读材料

比较简单,略。

Lab 07: Linked Lists, Inheritance

Q1: WWPD: Inheritance ABCs

略。

Q2: Retirement

http://www.kler.cn/a/530383.html

相关文章:

  • 使用PyQt5绘制带有刻度的温度计控件
  • 计算机毕业设计Python动漫推荐系统 漫画推荐系统 动漫视频推荐系统 机器学习 bilibili动漫爬虫 数据可视化 数据分析 大数据毕业设计
  • Unity游戏(Assault空对地打击)开发(3) 摄像机的控制
  • pytorch实现主成分分析 (PCA):用于数据降维和特征提取
  • 家居EDI:Hom Furniture EDI需求分析
  • MiniMind——跑通项目
  • WebShell分析
  • 使用 Elastic Cloud 中的异常检测来识别欺诈
  • UE5 蓝图学习计划 - Day 4:变量与函数基础
  • 5.5.1 面向对象的基本概念
  • 搜索与图论复习2最短路
  • 使用Z-score进行数据特征标准化
  • Rust 所有权特性详解
  • 谭浩强C语言程序设计(4) 8章(下)
  • Maven全解析:从基础到精通的实战指南
  • 利用DeepSeek提炼腾讯AI研究院的图景关键词——延伸畅想
  • Resnet 改进:尝试在不同位置加入Transform模块
  • LeetCode435周赛T2贪心
  • Elixir语言的安全开发
  • GWO优化LSBooST回归预测matlab
  • Java多线程与高并发专题——生产/消费者模式
  • XML DOM 节点树
  • ROS应用之AMCL 多机器人支持
  • Python-基于PyQt5,wordcloud,pillow,numpy,os,sys等的智能词云生成器(最终版)
  • C++编程语言:抽象机制:泛型编程(Bjarne Stroustrup)
  • 汇编语言运行环境搭建及简单使用