零基础人工智能第六周作业
Day1
第1题
类属性只能通过类名访问,不能通过实例访问。
判断:____
第2题
实例方法中的 self 参数在调用时由 Python 自动传入,不需要手动传递。
判断:____
第3题
静态方法可以通过 self 访问实例属性。
判断:____
第4题
使用 @classmethod 装饰的方法,第一个参数必须是 cls。
判断:____
第5题
在实例方法中修改类属性,必须使用 类名.属性 = 新值 或 self.__class__.属性 = 新值。
判断:____
第6题
__init__ 方法中定义的变量都是类属性。
判断:____
第7题
静态方法可以访问类属性,但需要传入 cls 参数。
判断:____
二、单项选择题
第9题
以下关于类属性的描述,错误的是:
A. 类属性在内存中只存储一份
B. 类属性可以通过 实例.属性 读取
C. 通过 实例.属性 = 新值 可以修改类属性
D. 类属性适合存放所有实例共享的数据
答案:____
第10题
以下哪个方法既不能访问实例属性,也不能访问类属性(除非显式传入)?
A. 实例方法
B. 类方法
C. 静态方法
D. 构造方法
答案:____
第11题
以下代码的输出结果是:
python
class Example:
data = [1, 2, 3]
e1 = Example()
e2 = Example()
e1.data.append(4)
print(e2.data)
A. [1, 2, 3]
B. [1, 2, 3, 4]
C. 报错
D. [4]
答案:____
第12题
以下代码的输出结果是:
python
class Test:
x = 5
t = Test()
t.x = 10
print(Test.x)
A. 5
B. 10
C. 报错
D. None
答案:____
第13题
关于 @classmethod 和 @staticmethod 的区别,下列说法正确的是:
A. 类方法可以访问实例属性,静态方法不可以
B. 静态方法可以访问类属性,类方法不可以
C. 类方法的第一个参数是 cls,静态方法没有特殊第一个参数
D. 两者功能完全相同,只是写法不同
答案:____
第14题
以下哪种情况不适合使用类方法?
A. 实现工厂方法(创建实例的替代方案)
B. 修改类级别的属性
C. 需要访问实例的 self.xxx 数据
D. 统计所有实例的数量
答案:____
三、填空题
第15题
在实例方法中,通过 ____________ 可以访问类属性。
第16题
若要在类方法中修改类属性,应使用 ____________ 参数来引用类。
第17题
实例方法的第一个参数通常命名为 ____________,类方法的第一个参数通常命名为 ____________,静态方法______(需要/不需要)特殊的第一参数。
第18题
以下代码中,total 是______属性,name 是______属性。
python
class Student:
total = 0
def __init__(self, name):
self.name = name
Student.total += 1
第19题
以下代码的输出结果是:______
python
class Demo:
value = "A"
def show(self):
print(self.value)
d = Demo()
d.value = "B"
d.show()
第20题
以下代码的输出结果是:______
python
class Parent:
tag = "parent"
class Child(Parent):
tag = "child"
c = Child()
print(c.tag)
第21题
以下代码的输出结果是:______
python
class Calculator:
@staticmethod
def add(a, b):
return a + b
@classmethod
def multiply(cls, a, b):
return a * b
print(Calculator.add(3, 4))
print(Calculator.multiply(3, 4))
F、T、F、T、T、F、F c、c、b、a、c、c 类名.属性名 cls self、cls、不需要 类属性、实例属性 B child 7、12
Day2
'''
1 学生成绩管理系统(基础类定义)
需求描述:
设计一个 Student 类,用于管理学生信息。
具体要求:
每个学生有:姓名(name)、学号(id)、成绩列表(scores,存储多个科目成绩)
提供方法:
add_score(subject, score):添加一门课的成绩
get_average():计算所有科目的平均分
get_highest():返回最高分
get_lowest():返回最低分
info():打印学生完整信息(姓名、学号、各科成绩、平均分)
# 测试代码
s = Student("张三", "2024001")
s.add_score("数学", 95)
s.add_score("英语", 88)
s.add_score("Python", 92)
print(s.get_average()) # 期望输出 91.67
print(s.info()) # 打印完整信息
class Student:
def __init__(self, name, ids):
self.name = name
self.id = ids
self.scores = {}
def add_score(self, subject, score):
self.scores[subject] = score
def get_average(self):
avg = sum(self.scores.values()) / len(self.scores)
return f'{avg:.2f}'
def get_highest(self):
return max(self.scores.values())
def get_lowest(self):
return min(self.scores.values())
def info(self):
lines = [f"姓名: {self.name}, 学号: {self.id}"]
for subject, score in self.scores.items():
lines.append(f"{subject}: {score}")
return lines
s = Student("张三", "2024001")
s.add_score("数学", 95)
s.add_score("英语", 88)
s.add_score("Python", 92)
print(s.get_average()) # 期望输出 91.67
print(s.info()) # 打印完整信息
'''
import types
'''
银行账户类(属性访问控制)
需求描述:
实现一个 BankAccount 类,模拟银行账户操作。
具体要求:
属性:account_id(账号)、owner(户主)、__balance(余额,私有属性)
方法:
:存款(金额必须 > 0)
withdraw(amount):取款(余额不足时提示并返回 False)
get_balance():查看余额(只读,不能直接修改)
transfer(target_account, amount):转账到另一个账户
__str__():返回账户信息
业务规则:
初始化时余额默认为 0
每次取款/存款打印操作日志
转账时需验证余额和对方账户存在
# 测试代码
acc1 = BankAccount("001", "张三")
acc2 = BankAccount("002", "李四")
acc1.deposit(1000)
acc1.withdraw(300)
acc1.transfer(acc2, 200)
print(acc1.get_balance()) # 期望 500
print(acc2.get_balance()) # 期望 200
acc1.__balance = 99999 # 尝试直接修改(应失败或无效)
print(acc1.get_balance()) # 仍为 500
class BankAccount:
def __init__(self,account_id ,owner , balance = 0):
self.account_id = account_id
self.owner = owner
self.__balance = balance
#存款
def deposit(self,amount):
if amount > 0:
self.__balance += amount
print(f'你有钱{self.__balance}')
else:
print('没钱了哥们')
#取款
def withdraw(self,amount):
if amount <= 0:
print('我分你点儿??')
return False
if amount > self.__balance:
print('别贪心哥们')
return False
else:
self.__balance -= amount
print(f'取出{amount},你还剩{self.__balance}')
return True
#查看余额
def get_balance(self):
return self.__balance
#转账
def transfer(self,target_account, amount):
if not isinstance(target_account,BankAccount):
print('没人')
return False
if self.withdraw(amount):
target_account.deposit(amount)
print(f'好心人给账户{target_account}转了{amount}')
return True
return False
#返回账户信息
def __str__(self):
return f"账户: {self.account_id}, 户主: {self.owner}, 余额: {self.__balance}"
acc1 = BankAccount("001", "张三")
acc2 = BankAccount("002", "李四")
acc1.deposit(1000)
acc1.withdraw(300)
acc1.transfer(acc2, 200)
print(acc1.get_balance()) # 期望 500
print(acc2.get_balance()) # 期望 200
acc1.__balance = 99999 # 尝试直接修改(应失败或无效)
print(acc1.get_balance()) # 仍为 500
'''
'''
3 银行账户升级版(类方法 + 静态方法)
需求描述:
升级银行账户系统,添加类级别的功能。
具体要求:
继承自题目 2 的 BankAccount(或重新设计)
添加类属性 bank_name(银行名称)和 total_accounts(总账户数)
添加 @classmethod 方法:
get_bank_info():返回银行名称和总账户数
create_account(owner, initial_balance=0):工厂方法创建账户
添加 @staticmethod 方法:
is_valid_amount(amount):验证金额是否合法(>0 且 < 10^9)
format_currency(amount):将金额格式化为 "¥1,234.56"
每次创建新账户时自动增加 total_accounts
添加 __del__ 方法,删除账户时减少总账户数
# 测试代码
print(BankAccount.get_bank_info()) # 输出: "Python银行, 当前总账户: 0"
acc1 = BankAccount.create_account("张三", 1000)
acc2 = BankAccount.create_account("李四")
print(BankAccount.total_accounts) # 期望 2
print(BankAccount.format_currency(1234.5)) # 期望 "¥1,234.50"
print(BankAccount.is_valid_amount(-5)) # 期望 False
# 删除账户测试
del acc1
print(BankAccount.total_accounts) # 期望 1
class BankAccount:
def __init__(self,account_id ,owner , __balance = 0):
self.account_id = account_id
self.owner = owner
self.__balance = __balance
#存款
def deposit(self,amount):
if amount > 0:
self.__balance += amount
print(f'你有钱{self.__balance}')
else:
print('没钱了哥们')
#取款
def withdraw(self,amount):
if amount <= 0:
print('我分你点儿??')
return False
if amount > self.__balance:
print('别贪心哥们')
return False
else:
self.__balance -= amount
print(f'取出{amount},你还剩{self.__balance}')
return True
#查看余额
def get_balance(self):
return self.__balance
#转账
def transfer(self,target_account, amount):
if not isinstance(target_account,BankAccount):
print('没人')
return False
if self.withdraw(amount):
target_account.deposit(amount)
print(f'好心人给账户{target_account}转了{amount}')
return True
return False
#返回账户信息
def __str__(self):
return f"账户: {self.account_id}, 户主: {self.owner}, 余额: {self.__balance}"
class BankAccount2(BankAccount):
bank_name = "LEECY银行"
total_accounts = 0
_account_counter = 0 # 私有类属性,生成唯一ID
def __init__(self,account_id ,owner , __balance = 0):
super().__init__(account_id ,owner , __balance)
#总账户
BankAccount2.total_accounts += 1
print(f"LEECY银行账户 {account_id} 创建成功!当前总账户: {BankAccount2.total_accounts}")
@classmethod
def get_bank_info(cls):
return f"银行名称:{cls.bank_name}, 当前总账户: {cls.total_accounts}"
@classmethod
def create_account(cls,owner ,initial_balance = 0):
"""
工厂方法:自动生成账户ID,创建新账户
"""
# 验证金额(0 可以放行作为初始值)
if initial_balance != 0 and not cls.is_valid_amount(initial_balance):
print("初始金额不合法")
return None
# 生成新ID
cls._account_counter += 1
account_id = f"{cls._account_counter:03d}" # 001, 002...
# 创建实例
return cls(account_id, owner, initial_balance)
"""
account_id = f"{cls.total_accounts + 1:04d}"
return cls(account_id, owner, initial_balance)
"""
@staticmethod
def is_valid_amount(amount):
return isinstance(amount, (int, float)) and 0 < amount < 10**9
@staticmethod
def format_currency(amount):
return f"¥{amount:,.2f}"
def __del__(self):
BankAccount2.total_accounts -= 1
print(f"LEECY银行账户 {self.account_id} 已注销。当前总账户: {BankAccount2.total_accounts}")
# 测试代码
print(BankAccount2.get_bank_info()) # 输出: "Python银行, 当前总账户: 0"
acc1 = BankAccount2.create_account("张三", 1000)
acc2 = BankAccount2.create_account("李四")
print(BankAccount2.total_accounts) # 期望 2
print(BankAccount2.format_currency(1234.5)) # 期望 "¥1,234.50"
print(BankAccount2.is_valid_amount(-5)) # 期望 False
# 删除账户测试
del acc1
print(BankAccount2.total_accounts) # 期望 1
'''
'''
4
需求描述
设计一个 Student 类,要求该类支持动态添加属性和方法,并实现一个成绩管理功能。
具体要求
基础类定义
类属性 school = "Python中学"
__init__ 方法接收 name 和 age 参数
动态属性管理:
实现 add_score(subject, score) 方法:动态添加成绩属性(如 math=95)
实现 get_scores() 方法:返回所有成绩属性的字典
实现 get_average() 方法:计算所有成绩的平均分
重要限制:只能将成绩属性添加到实例,不能修改类属性
动态方法扩展:
实现 add_method(method_name, func) 方法:为当前实例动态添加方法
添加的方法可以访问实例的属性和其他方法
# 测试代码
# 1. 创建实例
s = Student("小明", 18)
# 2. 动态添加成绩
s.add_score("math", 95)
s.add_score("english", 88)
s.add_score("python", 92)
# 3. 查看成绩
print(s.get_scores())
# 期望输出: {'math': 95, 'english': 88, 'python': 92}
print(s.get_average())
# 期望输出: 91.666...
# 4. 验证实例属性
print(s.math) # 期望: 95
print(s.english) # 期望: 88
# 5. 动态添加方法
def show_summary(self):
return f"{self.name} 的总分是: {sum(self.get_scores().values())}"
s.add_method("summary", show_summary)
print(s.summary())
# 期望输出: "小明 的总分是: 275"
# 6. 动态添加方法并访问实例属性
def praise(self):
# 根据具体的平均成绩返回优秀,良好等评级
s.add_method("get_praise", praise)
print(s.get_praise())
# 期望输出: "优秀!"
import types
class Student:
school = "LEECY中学"
def __init__(self, name, age):
self.name = name
self.age = age
#动态添加成绩属性
def add_score(self, subject, score):
setattr(self, subject, score)
#返回所有成绩属性的字典
def get_scores(self):
scores_dict = {}
for attr, value in self.__dict__.items():#只保留数值类型且属性名不是保留字段
if attr not in ('name', 'age') and isinstance(value, (int, float)):
scores_dict[attr] = value
return scores_dict
#计算所有成绩的平均分
def get_average(self):
scores = list(self.get_scores().values())
if not scores:
return 0
return sum(scores) / len(scores)
# 动态方法扩展:
def add_method(self,method_name, func):
"""为当前实例动态绑定一个方法(需使用 MethodType)"""
bound_method = types.MethodType(func, self)
setattr(self, method_name, bound_method)
# 测试代码
# 1. 创建实例
s = Student("小明", 18)
# 2. 动态添加成绩
s.add_score("math", 95)
s.add_score("english", 88)
s.add_score("python", 92)
# 3. 查看成绩
print(s.get_scores())
# 期望输出: {'math': 95, 'english': 88, 'python': 92}
print(s.get_average())
# 期望输出: 91.666...
# 4. 验证实例属性
print(s.math) # 期望: 95
print(s.english) # 期望: 88
# 5. 动态添加方法
def show_summary(self):
return f"{self.name} 的总分是: {sum(self.get_scores().values())}"
s.add_method("summary", show_summary)
print(s.summary())
# 期望输出: "小明 的总分是: 275"
# 6. 动态添加方法并访问实例属性
def praise(self):
# 根据具体的平均成绩返回优秀,良好等评级
avg = self.get_average()
if avg >= 90:
return "优秀!"
elif avg >= 80:
return "良好!"
elif avg >= 60:
return "及格!"
else:
return "不及格!"
s.add_method("get_praise", praise)
print(s.get_praise())
# 期望输出: "优秀!"
'''
Day3
'''
1.
class Example:
def __init__(self):
self.public = 1
self._protected = 2
self.__private = 3
e = Example()
# 以下哪些能正常执行?哪些会报错?
print(e.public)
print(e._protected)
print(e.__private)
'''
"""
答:前两行可以正常执行,第一行是公开属性;第二行是保护属性,规定不允许,弱私有属性;
第三行不可以执行,是私有属性,外部不能直接访问
"""
'''
class Parent:
def __init__(self):
self.__value = 10
def get_value(self):
return self.__value
class Child(Parent):
def __init__(self):
super().__init__()
self.__value = 20 # 这是新属性还是覆盖?
def show(self):
return self.__value
c = Child()
print(c.get_value()) # 输出什么?
print(c.show()) # 输出什么?
'''
"""
答:10,20,新属性
"""
'''
3.
class Circle:
def __init__(self, radius):
self.radius = radius
# 请补全代码:让 area 成为只读属性,通过 radius 计算面积(π取3.14)
要求:
area 通过 @property 实现,不能直接赋值
如果尝试 c.area = 100,应抛出 AttributeError
'''
"""
答:
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return self.radius**2 * 3.14
c = Circle(100)
print(c.area)
c.area = 100
print(c.area)
"""
'''
4.
class User:
def __init__(self, username, password):
self.username = username
self.password = password # 密码长度不能小于6位
要求:
使用 @property 和 setter 对 password 进行校验
密码长度 < 6 时抛出 ValueError
'''
"""
class User:
def __init__(self, username, password):
self.username = username
self.password = password # 密码长度不能小于6位
@property
def password(self):
return self.__password
@password.setter
def password(self, value):
if len(value) < 6:
raise ValueError
else:
self.__password = value
username = input('输入姓名:')
password = input('输入密码:')
user = User(username, password)
print(user.password)
"""
'''
5 设计一个银行账户类
请设计 BankAccount 类,满足以下要求:
初始化时传入 owner(账户名)和 balance(余额,默认0)
balance 不能直接外部修改
提供 deposit(amount) 方法:存款,金额必须 > 0
提供 withdraw(amount) 方法:取款,金额必须 > 0 且余额充足
提供只读属性 balance 查看余额
提供 get_transaction_history() 返回所有交易记录列表
'''
"""
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.__balance = balance
self.__history = []
#提供 deposit(amount) 方法:存款,金额必须 > 0
def deposit(self, amount):
if amount <= 0:
raise ValueError
else:
self.__balance += amount
record = {
'type': '存款',
'amount': amount,
'balance_after': self.__balance,
}
self.__history.append(record)
return self.__balance
#提供 withdraw(amount) 方法:取款,金额必须 > 0 且余额充足
def withdraw(self, amount):
if amount <= 0:
raise ValueError
else:
self.__balance -= amount
record = {
'type': '取款',
'amount': amount,
'balance_after': self.__balance,
}
self.__history.append(record)
return self.__balance
#提供只读属性 balance 查看余额
@property
def balance(self):
return self.__balance
#提供 get_transaction_history() 返回所有交易记录列表
def get_transaction_history(self):
return self.__history.copy()
account1 = BankAccount('as',12345)
account2 = BankAccount('bs',54321)
account1.deposit(200)
account1.withdraw(100)
account2.deposit(200)
account2.withdraw(100)
print(account1.balance)
print(account1.get_transaction_history())
print(account2.balance)
print(account2.get_transaction_history())
"""
Day4
'''
1. 在Python中,子类继承父类时,以下哪种说法是正确的?
A. 子类会自动继承父类的所有属性和方法(包括私有属性)
B. 子类必须重写父类的所有方法
C. 子类可以通过 super() 调用父类的方法
D. 一个子类只能继承一个父类
C
'''
'''
2. 现有以下代码,输出结果为:
class A:
def show(self):
print("A")
class B(A):
def show(self):
print("B") #重写
class C(B):
pass
obj = C()
obj.show()
A. A
B. B
C. 报错
D. 无输出
B
'''
'''
3.关于 super() 函数的描述,错误的是:
A. super() 可以在子类中调用父类的方法
B. super() 只能用在 __init__ 方法中
C. super() 可以解决多继承中的钻石问题(菱形继承) 按 MRO 顺序调用,解决钻石继承问题
D. super() 返回的是一个代理对象
B
'''
'''
4. 以下代码的输出结果是:
class X:
def __init__(self):
self.a = 10
class Y(X):
def __init__(self):
super().__init__()
self.a += 5
obj = Y()
print(obj.a)
A. 10
B. 15
C. 报错
D. 5
B
'''
'''
填空题:
在子类中重写父类的方法时,可以使用 ______ 函数来调用父类的同名方法。
若子类没有定义 __init__ 方法,则实例化子类时会自动调用父类的 __________ 方法。
查看一个类的 MRO(方法解析顺序)可以使用 类名.__________。
所有Python类都隐式继承自内置类 __________。
如果子类定义了与父类同名的属性,则子类实例访问该属性时,优先使用 __________ 类的属性。
super(). 父类名.方法()
__init__
__mro__
object
子类
'''
'''
判断题
1.__private_attr 形式的私有属性在子类中可以直接被访问。( )
2.super().__init__() 必须在子类 __init__ 的第一行调用,否则会报错。( )
F F
'''
'''
简答题
1. 简述方法重写(Override)。
答案 记忆 重写是子类重新定义父类方法,同名覆盖
2. 说明 super() 在单继承和多继承中分别起到了什么作用。
答案: 记忆一下即可 单继承中调用父类方法;多继承中按MRO顺序调用下一个类的方法,避免重复调用
3. 什么是“菱形继承”(钻石继承)?Python 是如何解决菱形继承中的方法冲突问题的?
答案 记忆一下即可 一个子类继承自两个父类,而这两个父类又继承自同一个基类,形成菱形.
Python通过C3线性化算法计算MRO,保证每个父类只被调用一次。
4. 请解释 __new__ 和 __init__ 在继承链中的调用顺序,以及它们在对象创建过程中的分工。
答案: 先调用 __new__(负责创建实例对象),再调用 __init__(负责初始化实例属性)。
继承链中:
__new__ 会沿 MRO 向上查找,直到找到能返回实例的类(通常是 object.__new__)。
__init__ 同样沿 MRO 调用,但只有当 __new__ 返回的是当前类的实例时,__init__ 才会被自动调用。
分工:__new__ 控制对象的创建(分配内存、返回实例),__init__ 控制对象的初始化(设置属性)。在继承中,
通常只重写 __init__,很少重写 __new__。
'''
'''
编程题:
设计一个基础类 Person,包含属性 name 和 age,以及方法 introduce() 返回 "我叫{name},今年{age}岁"。
创建子类 Student,新增属性 grade(年级),重写 introduce() 方法,返回 "我叫{name},今年{age}岁,在读{grade}年级"。
再创建子类 Teacher,新增属性 subject(科目),重写 introduce() 方法,返回 "我叫{name},今年{age}岁,教{subject}课"。
要求:
子类必须通过 super() 复用父类的初始化逻辑。
创建至少一个 Student 实例和一个 Teacher 实例,调用它们的 introduce() 方法并打印结果。
写出完整的可运行代码。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
return f'我叫{self.name}, 今年{self.age}岁'
class Student(Person):
def __init__(self, name, age,grade):
super().__init__(name, age)
self.grade = grade
def introduce(self):
return f'我叫{self.name},今年{self.age}岁,在读{self.grade}年级'
class Teacher(Person):
def __init__(self, name, age,subject):
super().__init__(name, age)
self.subject = subject
def introduce(self):
return f'我叫{self.name},今年{self.age}岁,教{self.subject}课'
s = Student("lee", 21, 6)
t = Teacher("l老师", 25, "数学")
print(s.introduce())
print(t.introduce())
'''
Day5
'''
场景二:电商平台的动态折扣策略(策略模式)
场景描述:
你正在为一个电商平台编写购物车结算模块。平台针对不同等级的会员(普通用户、VIP用户、钻石用户)有不同的折扣计算方式。为了避免在结算函数里写一堆 if-elif 判断,你需要利用多态来动态切换折扣算法。
练习要求:
定义一个基类 DiscountStrategy,包含一个 apply_discount(price) 方法。
创建三个子类:NormalDiscount(9折)、VipDiscount(7折)、DiamondDiscount(5折),分别实现具体的折扣计算逻辑。
定义一个 ShoppingCart(购物车)类,在初始化时接收一个折扣策略对象。
在购物车的 checkout(total_price) 方法中,调用当前策略对象的 apply_discount 方法计算最终价格。
测试:为同一个购物车动态切换不同的折扣策略,验证结算结果。
'''
'''
from abc import ABC,abstractmethod
class DiscountStrategy(ABC):
@abstractmethod
def apply_discount(self, price):
pass
@abstractmethod
def name(self):
pass
#用户结构算法
#9
class NormalDiscount(DiscountStrategy):
@property
def name(self):
return '普通会员'
def apply_discount(self, price):
return price*0.9
#7
class VipDiscount(DiscountStrategy):
@property
def name(self):
return 'VIP会员'
def apply_discount(self, price):
return price*0.7
#5
class DiamondDiscount(DiscountStrategy):
@property
def name(self):
return '钻石用户'
def apply_discount(self, price):
return price * 0.5
#车
class ShoppingCart:
def __init__(self,structure:DiscountStrategy):
self.structure = structure
self.items = []
#加商品
def add (self,name,price):
self.items.append((name,price))
#判断用户结构
def judge_structure(self,structure:DiscountStrategy):
self.structure = structure
# #最终价格
def checkout(self):
#总价
total =sum(price for _,price in self.items)
#折后
final = self.structure.apply_discount(total)
print(f"\n【{self.structure.name}】结算\n商品: {self.items}\n原价: ¥{total:.2f}\n折后: ¥{final:.2f}")
return final
p = ShoppingCart(NormalDiscount())
p.add('电脑',10000)
p.add('手机',8000)
p.judge_structure(NormalDiscount())
p.checkout()
p.judge_structure(VipDiscount())
p.checkout()
p.judge_structure(DiamondDiscount())
p.checkout()
'''
'''
场景三:多源数据提取管道(接口统一)
场景描述:
你的后端系统需要处理来自不同渠道的用户数据,包括 JSON 格式的 API 响应、数据库查询返回的字典,以及 CSV 文件解析出的列表。虽然数据结构不同,但业务层只需要统一获取 user_id。请利用多态设计一个数据提取管道。
练习要求:
定义一个基类 DataExtractor,包含一个 extract_user_id() 方法。
创建三个子类:JsonExtractor、DbExtractor、CsvExtractor,在各自的 __init__ 中接收原始数据,并在 extract_user_id() 中实现针对该数据格式的提取逻辑。
编写一个 process_data(extractor) 函数,不关心传入的具体提取器类型,只调用 extract_user_id() 获取结果并打印。
构造三种格式的测试数据,验证数据提取管道的通用性。
'''
'''
from abc import ABC, abstractmethod
import json
import csv
import io
# ========== 抽象提取器 ==========
class DataExtractor(ABC):
@abstractmethod
def extract_user_id(self):
pass
# ========== JSON 提取器 ==========
class JsonExtractor(DataExtractor):
def __init__(self, raw_data: str):
self.data = json.loads(raw_data)
def extract_user_id(self):
return self.data.get("user_id") or self.data.get("id")
# ========== 数据库提取器 ==========
class DbExtractor(DataExtractor):
def __init__(self, raw_data: dict):
self.data = raw_data
def extract_user_id(self):
# 数据库字段可能是 user_id / uid / id
for key in ["user_id", "uid", "id"]:
if key in self.data:
return self.data[key]
return None
# ========== CSV 提取器 ==========
class CsvExtractor(DataExtractor):
def __init__(self, raw_data: str):
# CSV 格式: "user_id,name,age\n1001,Alice,25"
reader = csv.DictReader(io.StringIO(raw_data))
self.rows = list(reader)
def extract_user_id(self):
if self.rows:
row = self.rows[0]
return row.get("user_id") or row.get("id")
return None
# ========== 统一处理函数 ==========
def process_data(extractor: DataExtractor):
user_id = extractor.extract_user_id()
print(f"提取到 user_id: {user_id}")
return user_id
# ========== 测试 ==========
print("=== JSON 数据 ===")
json_data = '{"user_id": "J1001", "name": "Alice"}'
process_data(JsonExtractor(json_data))
print("\n=== 数据库数据 ===")
db_data = {"uid": "D2002", "name": "Bob", "age": 30}
process_data(DbExtractor(db_data))
print("\n=== CSV 数据 ===")
csv_data = "user_id,name,age\nC3003,Carol,25"
process_data(CsvExtractor(csv_data))
'''
'''
from abc import ABC,abstractmethod
#统一id
class DataExtractor(ABC):
@abstractmethod
def extract_user_id(self):
pass
#json
class JsonExtractor(DataExtractor):
def __init__(self, raw_data: str):
self.raw_data = raw_data
def extract_user_id(self):
return 'json'
#sql{}
class DbExtractor(DataExtractor):
def __init__(self, raw_data: dict):
self.raw_data = raw_data
def extract_user_id(self):
return 'sql{}'
#csv
class CsvExtractor(DataExtractor):
def __init__(self, raw_data: str):
self.raw_data = raw_data
def extract_user_id(self):
return 'csv'
#结果函数
def process_data(extractor: DataExtractor):
print(extractor.extract_user_id())
j_str = {}
process_data(JsonExtractor(j_str))
db_dict = {}
process_data(DbExtractor(db_dict))
csv_str = {}
process_data(CsvExtractor(csv_str))
'''
'''
场景四:音乐厅的乐器演奏测试(抽象类与多态)
场景描述:
一家音乐厅需要测试新入库的乐器。乐器分为钢琴(Piano)和小提琴(Violin),它们都有“演奏(play)”的行为,但具体表现完全不同。为了保证所有入库的乐器都具备演奏功能,你需要使用抽象类来强制规范。
练习要求:
使用 Python 的 abc 模块定义一个抽象基类 Instrument,包含抽象方法 play()。
定义 Piano 和 Violin 继承 Instrument,并分别实现 play() 方法(例如打印“正在演奏钢琴曲”和“正在演奏小提琴曲”)。
编写一个 test_play(instrument) 测试函数,接收 Instrument 类型的对象并调用 play()。
尝试直接实例化 Instrument 类(应报错),然后实例化子类并传入测试函数,验证多态行为。
'''
'''
from abc import ABC,abstractmethod
#instrument
class Instrument(ABC):
@abstractmethod
def play(self):
pass
@property
@abstractmethod
def name(self):
pass
#piano
class Piano(Instrument):
@property
def name(self):
return 'Piano'
def play(self):
return "弹"
#violin
class Violin(Instrument):
@property
def name(self):
return 'Violin'
def play(self):
return '拉'
#test_play
def test_play(instrument:Instrument):
test = instrument.play()
print(f'乐器名:{instrument.name}\n{test}')
for instrument in [Piano(),Violin()]:
test_play(instrument)
#尝试直接实例化 Instrument 类(应报错)
i = Instrument()
i.play()
'''
更多推荐

所有评论(0)