# -*- coding: utf-8 -*- from abc import ABC ,abstractclassmethod from collections import namedtuple Customer = namedtuple('Customer','name fidelity') class lineItem: """初始化明细行:产品、数量、单价""" def __init__(self,product,qty,price): self.product = product self.qty = qty self.price = price def total(self): return self.price*self.qty class Order: """客户、购物车、 促销活动""" def __init__(self, customer, cart, promotion=None): self.customer = customer self.cart = list(cart) self.promotion = promotion def total(self): """hasattr:用法:判断是否包含对应的属性""" if not hasattr(self,'__total'): self.__total = sum(item.total() for item in self.cart) #计算购物车里总金额 return self.__total def due(self): if self.promotion is None: discount=0 else: discount = self.promotion.discount(self) return self.total()-discount def __repr__(self): fmt = '<Order total:{:.2f} due :{:.2f}>' return fmt.format(self.total(),self.due()) class Promotion(ABC): #策略 抽象基类 """ @abstractmethod:抽象方法,含abstractmethod方法的类不能实例化,继承了含abstractmethod方法的子类必须复写所有abstractmethod装饰的方法,未被装饰的可以不重写 @ property:方法伪装属性,方法返回值及属性值,被装饰方法不能有参数,必须实例化后调用,类不能调用 @ classmethod:类方法,可以通过实例对象和类对象调用,被该函数修饰的方法第一个参数代表类本身常用cls,被修饰函数内可调用类属性,不能调用实例属性 @staticmethod:静态方法,可以通过实例对象和类对象调用,被装饰函数可无参数,被装饰函数内部通过类名.属性引用类属性或类方法,不能引用实例属性 """ @abstractclassmethod def discount(self,order): """返回折扣金额、""" class FidelityPromo(Promotion): #策略1 """积分为1000或以上的客户提供5%的折扣""" def discount(self,order): return order.total()*0.05 if order.customer.fidelity>=1000 else 0 class BulkItemPromo(Promotion):#策略2 """单个商品为20个或以上时提供10%的折扣""" def discount(self,order): discount = 0 for item in order.cart: if item.quantity>=20: discount+=item.total()*0.1 return discount class LargeOrderPromo(Promotion):#策略3 """订单中不同商品达到10个或以上时提供7%的折扣""" def discount(self, order): discount_items = {item.product for item in order.cart} if len(discount_items)>=10: return order.total()*0.07 return 0