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()
'''

更多推荐