Python技能树学习-类

题目一:Python类的基本使用(1)

下面的类封装了一组 set/get/keys 接口

# -*- coding: UTF-8 -*-
class KeyValueSet:
    def __init__(self) -> None:
        self.dict = {}

    def set(self, key, value):
        self.dict[key] = value

    def get(self, key):
        return self.dict.get(key)

    def keys(self):
        return self.dict.keys()

请你使用类 KeyValueSet 完成一个交互式命令行你想我猜游戏。支持:

  • 装载N个句子对
  • 你猜我想 闯关,输出上半句,等待用户猜测下半句
  • 如果猜中就累加10分,否则扣2分
  • 全部结束输出用户本次得分

我们编写一个新的class,内部通过组合KeyValueSet来支持上述功能,程序框架如下:

# -*- coding: UTF-8 -*-
class GuessSentenceGame:
    def __init__(self):
        self.kv = KeyValueSet()
        self.score = 0

    def setup(self, sentences):
        # TODO(You): 请在此编写装载逻辑
    
    def guess(self, first_word):
        # TODO(You): 请在此编写猜测结果,返回 err, value
    
    def run(self):
        self.score = 0
        for first_word in self.kv.keys():
            ret = input("猜一猜下半句是什么? {} -> :".format(first_word))
            err, value = self.guess(first_word)
            if err==0:
                print('你太厉害了,这都能猜得到!+10分!')
                self.score += 10
            else:
                self.score -= 2
                print('哈哈,肯定猜不到得啦:{}->{},扣除2分!'.format(first_word, value))
        print('游戏结束,你本次游戏得分:', self.score)

if __name__ == '__main__':

    sentences = [
        "hello world",
        'monkey king',
        'tomorrow is another day',
        "good bye"
    ]

    game = GuessSentenceGame()
    game.setup(sentences)
    game.run()

示例输出:

一个示例输出是:

猜一猜下半句是什么? hello -> :world
你太厉害了,这都能猜得到!+10分!
猜一猜下半句是什么? monkey -> :king
你太厉害了,这都能猜得到!+10分!
猜一猜下半句是什么? tomorrow -> :is another day
你太厉害了,这都能猜得到!+10分!
猜一猜下半句是什么? good -> :a
哈哈,肯定猜不到得啦:good->bye,扣除2分!
游戏结束,你本次游戏得分: 28

请选出下面的实现代码中,错误 的选项。

实现

 

# 第一种方法

class GuessSentenceGame:
    ...

    def setup(self, sentences):
        for sentence in sentences:
            cut_pos = sentence.find(' ')
            first_word, rest = sentence[0:cut_pos], sentence[cut_pos+1:].strip()
            self.kv.set(first_word, rest)

    def guess(self, first_word):
        value = self.kv.get(first_word)
        err = 0 if value else 1
        return err, value
# 第二种方法
class GuessSentenceGame:
    ...

    def setup(self, sentences):
        for sentence in sentences:
            self.append(sentence)

    def append(self, sentence):
        cut_pos = sentence.find(' ')
        first_word, rest = sentence[0:cut_pos], sentence[cut_pos+1:].strip()
        self.kv.set(first_word, rest)
    
    def guess(self, first_word):
        ret = self.kv.get(first_word)
        if ret is None:
            return 1, None
        else:
            return 0, ret

# 第三种方法
class GuessSentenceGame:
    ...

    def setup(self, sentences):
        for sentence in sentences:
            first_word, rest = self.parse_sentence(sentence)
            self.kv.set(first_word, rest)
    
    def parse_sentence(self, sentence):
        cut_pos = sentence.find(' ')
        return sentence[0:cut_pos], sentence[cut_pos+1:].strip()

    def guess(self, first_word):
        value = self.kv.get(first_word)
        return 0, value if value else 1, None

主要是代码结构和责任划分不同:

  • 方法一:直接设置键值对。在setup方法中,直接遍历句子列表,对每个句子执行分割操作,然后将分割得到的第一个单词和剩余部分设置为键值对。职责集中:所有操作(包括分割句子和设置键值对)都在setup方法内部完成,没有额外的方法调用。
  • 方法二:通过额外的方法处理句子。在setup方法中,通过调用append方法来处理每个句子。这种设计提供了更好的模块化。职责分离:append方法负责处理单个句子的分割和键值对设置,而 setup 仅负责遍历句子列表。
  • 方法三:进一步模块化。通过 parse_sentence 方法专门处理句子的解析。职责高度分离parse_sentence 负责句子的分割和格式化,setup 方法则只负责调用parse_sentence 和设置键值对。改进:guess 方法中的返回结构似乎有笔误,应该是 return 0, value if value else (1, None),这样就统一了返回格式和清晰地处理了空值情况。

错误答案分析

class GuessSentenceGame:
    ...

    def setup(sentences):
        for sentence in sentences:
            cut_pos = sentence.find(' ')
            self.kv.set(sentence[0:cut_pos], sentence[cut_pos+1:].strip())
        
    def guess(first_word):
        self.kv.get(first_word)
        return 0, value if value else 1, None

# 定义缺少'self'参数

# 在guess方法中,变量value未定义

# 返回值格式问题

更改后代码:

class GuessSentenceGame:
    ...

    def setup(self,sentences):
        for sentence in sentences:
            cut_pos = sentence.find(' ')
            self.kv.set(sentence[0:cut_pos], sentence[cut_pos+1:].strip())
        
    def guess(self,first_word):

        value = self.kv.get(first_word)

        return (0, value) if value else (1, None)

 

题目二:Python类的基本使用(2)

在上一题的基础上。通过类的集成,可以扩展原有的类。例如继承KeyValueSet容器类,扩展功能,支持类似redis的 hset/hget/hkeys 扩展接口

基本代码框架如下

# -*- coding: UTF-8 -*-
from key_value_set import KeyValueSet

class HashKeyValueSet(KeyValueSet):
    def __init__(self) -> None:
        super().__init__()

    def hset(self, hash_key, key, value):
        # TODO(You): 请在此实现 hset 方法

    def hget(self, hash_key, key):
        hash_set = self.get(hash_key)
        if hash_set is None:
            return None
        else:
            return hash_set.get(key)

    def hkeys(self, hash_key):
        hash_set = self.get(hash_key)
        if hash_set is None:
            return []
        else:
            return hash_set.keys()

用例如下:

# -*- coding: UTF-8 -*-
if __name__ == '__main__':
    hashset = HashKeyValueSet()

    hashset.hset('puzzle', 'hello', 'world!')
    hashset.hset('puzzle', 'monkey', 'king!')
    hashset.hset('puzzle', 'tomorrow', 'is another day')
    hashset.hset('puzzle', 'good', 'bye!')

    keys = hashset.hkeys('puzzle')
    for key in keys:
        ret = input("猜一猜下半句是什么? {} -> :".format(key))
        value = hashset.hget('puzzle', key)
        if ret == value:
            print('你太厉害了,这都能猜得到!')
        else:
            print('哈哈,肯定猜不到得啦:{}->{}'.format(key, value))

实现

# 第一种方法

self.set(hash_key, {key:value})


# 第二种方法

hash_set = self.get(hash_key)
if hash_set is None:
    hash_set = {key:value}
else:
    hash_set[key] = value

self.set(hash_key, hash_set)

# 第三种方法

hash_set = self.get(hash_key)
if hash_set is None:
    hash_set = {key:value}
    self.set(hash_key, hash_set)
else:
    hash_set[key] = value
    self.set(hash_key, hash_set)
  • 方法一:直接设置给定的hash_key到一个新的字典,其中只包含单一的键值对{key: value}。如果该hash_key之前已经存在且包含其他键值对,那么这些键值对将被新的字典覆盖。这种方法会导致数据丢失,除非每次只想维持一个键值对。
  • 方法二(最优):首先检查hash_key是否已经存在,如果不存在,创建一个新的字典并设置该键值对。如果存在,就在已有的字典中添加或更新键值对,并重新设置到hash_key。保证了数据的完整性,并能正确地更新或添加键值对。
  • 方法三:与第二种类似,但在每个条件分支中都调用了self.set。效果与第二种方法相同,但稍微增加了代码的冗余,因为在hash_set已经存在的情况下,可以仅更新字典而不是每次都调用self.set

错误答案分析

hash_set = self.get(hash_key,{key:value})
self.set(hash_key, hash_set)

# 不能正确地处理键值对的更新,还可能导致混淆,看起来像是在尝试更新或设置值,实际上并没有这么做。正确的做法是明确检查hash_key是否存在,如方法二所示,然后根据情况更新或添加键值对,并确保这些更改反映到存储结构中。

 

题目三:Python类的基本使用(3)

基于第1题,还可以通过类的组合,使用组合而非继承实现类的扩展,支持类似 redis 的 hset/hget/hkeys 扩展接口。

相比于本节第2题,下面代码使用组合的方式复合KeyValueSet的功能,从而实现HashKeyValueSet。

# -*- coding: UTF-8 -*-
from key_value_set import KeyValueSet

class HashKeyValueSet:
    def __init__(self, kvset) -> None:
        super().__init__()
        self.kvset = kvset

    def hset(self, hash_key, key, value):
        # TODO(You): 请在此添加代码

    def hget(self, hash_key, key):
        hash_set = self.kvset.get(hash_key)
        if hash_set is None:
            return None
        else:
            return hash_set.get(key)

    def hkeys(self, hash_key):
        hash_set = self.kvset.get(hash_key)
        if hash_set is None:
            return []
        else:
            return hash_set.keys()

类HashKeyValueSet的用例如下:

def test():
    hashset = HashKeyValueSet(KeyValueSet())

    hashset.hset('puzzle', 'hello', 'world!')
    hashset.hset('puzzle', 'monkey', 'king!')
    hashset.hset('puzzle', 'tomorrow', 'is another day')
    hashset.hset('puzzle', 'good', 'bye!')

    keys = hashset.hkeys('puzzle')
    for key in keys:
        ret = input("猜一猜下半句是什么? {} -> :".format(key))
        value = hashset.hget('puzzle', key)
        if ret == value:
            print('你太厉害了,这都能猜得到!')
        else:
            print('哈哈,肯定猜不到得啦:{}->{}'.format(key, value))

if __name__ == '__main__':
    test()

实现

# 第一种方法

hash_set = self.kvset.get(hash_key)
if hash_set is None:
    hash_set = {}
    hash_set[key] = value
    self.kvset.set(hash_key, hash_set)
else:
    hash_set[key] = value
    self.kvset.set(hash_key, hash_set)


# 第二种方法

self.kvset.set(hash_key, {key: value})

# 第三种方法

hash_set = self.kvset.get(hash_key)
if hash_set is None:
    hash_set = {key: value}
else:
    hash_set[key] = value
self.kvset.set(hash_key, hash_set)

在处理数据更新和键值对保存的方式上有所不同:

  • 方法一:首先检查hash_key是否已存在。如果不存在,则创建一个新的字典,并添加键值对,然后保存。如果存在,则在现有的字典中添加或更新键值对,并重新保存。这种方法保证了数据的完整性,并且正确处理了新旧键值对的添加和更新。
  • 方法二:每次调用时都会创建一个只包含单个键值对的新字典,并将其设置为hash_key的值。这会导致hash_key原有的数据被覆盖,如果hash_key下已经存储了其他键值对,那么这些数据将丢失。这种方法适用性有限,只有在确定不需要旧数据时才适用。
  • 方法三(最优):与第一种方法类似,但更简洁。它检查hash_key是否存在,然后相应地创建新字典或更新现有字典,最后保存。这种方法既保留了数据完整性,也有效地管理了新旧数据的更新。。

错误答案分析

self.set(hash_key, {key: value})

# 主要问题在于它不考虑已存在的数据,直接覆盖整个值

 

学习 Python 所需掌握的技能体系或知识结构涵盖了从基础语法到高级应用的多个层面,具体可以分为以下几个模块: ### 基础语法与编程概念 - **变量与数据型**:包括整型、浮点型、字符串等基本数据型的使用。 - **控制流**:掌握 if 语句、for 循环、while 循环等控制程序流程的方法。 - **函数**:定义和调用函数,理解参数传递机制。 - **模块与包**:了解如何导入和使用标准库和其他第三方库。 ### 数据结构与算法 - **列表、字典、集合等数据结构**:熟悉这些内置数据结构的操作及其应用场景。 - **文件操作**:读写文件,处理文本数据。 - **异常处理**:使用 try-except 块来捕获并处理错误。 ### 面向对象编程 - **与对象**:创建,实例化对象,定义属性和方法。 - **继承与多态**:实现之间的继承关系,利用多态性提高代码灵活性。 ### 进阶主题 - **装饰器与上下文管理器**:增强函数功能而不修改其内部逻辑。 - **生成器与协程**:高效处理大量数据流。 - **元编程**:通过反射机制动态修改程序行为。 ### 应用开发 - **Web 开发**:使用 Flask 或 Django 构建 Web 应用程序。 - **网络爬虫**:利用 Scrapy 或 BeautifulSoup 抓取网页信息。 - **图形用户界面(GUI)**:使用 Tkinter 或 PyQt 创建 GUI 程序。 ### 科学计算与数据分析 - **NumPy**:进行高效的数值运算。 - **Pandas**:处理表格型数据,执行复杂的数据分析任务。 - **Matplotlib & Seaborn**:绘制图表以直观展示数据结果。 - **SciPy**:解决科学和技术计算中的常见问题。 ### 人工智能与机器学习 - **Scikit-learn**:实施经典的机器学习模型。 - **TensorFlow / Keras / PyTorch**:构建深度学习模型。 - **自然语言处理(NLP)**:使用 NLTK 或 spaCy 处理文本数据。 ### 软件工程实践 - **版本控制系统**:熟练使用 Git 来跟踪代码变更历史。 - **测试驱动开发(TDD)**:编写单元测试确保代码质量。 - **持续集成/部署(CI/CD)**:自动化测试和部署流程。 ### 开发工具与环境配置 - **Anaconda**:管理 Python 环境及依赖项。 - **Conda 虚拟环境**:为不同项目设置独立的运行环境。 - **VSCode**:配置 Python 扩展及其他插件提升编码效率。 ### AI 编程辅助 - **智能问答系统**:借助 AI 工具快速解答技术难题。 - **代码补全与重构建议**:获得实时反馈优化代码质量。 - **文档生成**:自动生成 API 文档简化维护工作。 以上所述构成了一个全面的学习路径[^3]。对于初学者而言,建议按照上述顺序逐步深入,同时结合实际项目练习巩固所学知识。随着技术水平的不断提升,还可以探索更多领域如网络安全、游戏开发等[^1]。 ```python # 示例:简单的 Python 函数示例 - 计算两个数之和 def add_numbers(a, b): """返回两个数字相加的结果""" return a + b result = add_numbers(5, 7) print("The result is:", result) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值