流畅的Python(六)-使用一等函数实现设计模式

一、核心要义

《设计模式:可复用面向对象软件的基础》一书中有23个设计模式,其中有16个在动态语言中"不见了或者简化了"。作为动态语言之一的Python, 我们可以利用一等函数简化其中的某些设计模式,本章主要介绍如何使用一等函数重构”策略“模式(关于何为策略模式,可参考策略设计模式)。

二、案例基本描述

用户购置商品,根据不同条件(用户会员积分、单类商品数量、购买的不同商品种类数量),享有不同的优惠策略,最后结算扣除优惠后应该支付的金额。

实体包括:

  • 用户:使用具名元组,包含名字会员积分两个属性
  • 单类商品订单:使用类,包含商品名称商品数量单价和三个属性
  • 优惠策略

     (1)如果用户积分大于1000,享受5%优惠

     (2)单类商品为20个及以上时,享受10%折扣

     (3)购买的不同商品种类数量达到3个或以上,享受7%折扣

二、代码示例

1、案例涉及前置知识

   (1)globals

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/1/27 12:31
# @Author  : Maple
# @File    : 00-相关背景知识.py
# @Software: PyCharmdef fun1(a,b):return a + bclass Person:def __init__(self,name,age):self.name = nameself.age = agedef reading(self):passRATIO = 1.2if __name__ == '__main__':g = globals()# 获取当前模块的相关信息(包名,模块路径,模块包含的函数,类等)print(g) # {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000018405083DC0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/01-study/python/fluent_python/06-设计模式/00-相关背景知识.py', '__cached__': None, 'fun1': <function fun1 at 0x000001840543D1F0>, 'Person': <class '__main__.Person'>, 'RATIO': 1.2, 'g': {...}}

   (2)获取当前模块所包含的所有函数

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/1/22 22:16
# @Author  : Maple
# @File    : promotions.py
# @Software: PyCharmimport inspect
import promotions"""
获取当前模块包含的所有函数
"""def f1():passdef f2():passif __name__ == '__main__':print(promotions) # <module 'promotions' from 'D:\\01-study\\python\\fluent_python\\06-设计模式\\promotions.py'>pros = [func for name,func in inspect.getmembers(promotions,inspect.isfunction)]print(pros) # [<function f1 at 0x00000217F33E5C10>, <function f2 at 0x00000217F36539D0>]

2、策略模式传统写法

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/1/27 9:48
# @Author  : Maple
# @File    : 01-策略模式传统写法.py
# @Software: PyCharm
from abc import ABC, abstractmethod
from collections import namedtuple# 顾客具名元组
Customer = namedtuple('Customer','name fidelity')# # 定义商品类
class Item:def __init__(self,product,quantity,price):""":param product: 商品名称:param quantity: 商品数量:param price: 商品单价"""self.product = productself.quantity = quantityself.price = pricedef totol(self):""":return:订单总费用"""return self.quantity * self.price# 定义上下文
class Order:def __init__(self,customer,cart,promotion=None):""":param customer: 顾客:param cart: 购物车:param promotion: 优惠策略"""self.customer = customerself.cart = cartself.promotion = promotiondef total(self):""":return:顾客订单打折之前的总费用"""if not hasattr(self,'__total'):self.__total = sum(item.totol() for item in self.cart)return self.__totaldef due(self):""":return:顾客最终支付的费用"""if self.promotion is None:return self.total()return self.total() - self.promotion.discount(self)def __repr__(self):fmt = '<Order total: {:.2f} due: {:.2f}>'return fmt.format(self.total(),self.due())# 定义优惠策略的基类
class BasePromotion(ABC):@abstractmethoddef discount(self,order):"""返回折扣金额"""# 具体策略1:积分优惠策略
class FidelityPromo(BasePromotion):"""如果积分大于1000,享受5%优惠"""def discount(self,order):if order.customer.fidelity > 1000:return order.total() * 0.05else:return 0# 具体策略2
class BulkItempromo(BasePromotion):"""单个商品为20个及以上时,提供10%折扣"""def discount(self,order):discount = 0for item in order.cart:if item.quantity >= 10:discount += item.totol()* 0.1return discount# 具体策略3
class LargetOrderPromo(BasePromotion):"""购物车中不同商品种类数量达到3个或以上提供7%折扣"""def discount(self,order):discount = 0# 获取购物车中所有不同的商品products = {item.product for item in order.cart}if len(products) >=3:discount += order.total() * 0.07return discountif __name__ == '__main__':#1. 策略1示例cus1 = Customer('Maple',2000) # 用户积分大于1000,享受5%优惠cart1=[Item('banana',20,2.0),Item('apple',10,1.0)]p1 = FidelityPromo()o1 = Order(cus1,cart1,p1)print(o1) # <Order total: 50.00 due: 47.50> 47.5 =  (40 + 10 - 50 *0.05)# 2. 策略2示例cus2 = Customer('Jack',880)cart2= [Item('Book',30,1.0),Item('Radio',5,1.0)] # Book订单超过20个,提供10%折扣p2 = BulkItempromo()o2 = Order(cus2,cart2,p2)print(o2)  # <Order total: 35.00 due: 32.00>  32.00 =  (30 -30 * 0.1) +  5# 策略3示例cus3 = Customer('Mick', 500)cart3 = [Item('Phone', 5, 2.0), Item('Water', 5, 1.0),Item('ring',20,2)] #购物车不同商品达到3个.提供7%折扣p3 = LargetOrderPromo()o3 = Order(cus3, cart3, p3)print(o3)  # <Order total: 55.00 due: 51.15> 51.15> =  (40 + 10 - 50 *0.05)

3、策略模式函数写法

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/1/27 11:25
# @Author  : Maple
# @File    : 02-策略模式函数写法.py
# @Software: PyCharm#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/1/27 9:48
# @Author  : Maple
# @File    : 01-策略模式传统写法.py
# @Software: PyCharm
from abc import ABC, abstractmethod
from collections import namedtuple# 顾客具名元组
Customer = namedtuple('Customer','name fidelity')# 定义商品类
class Item:def __init__(self,product,quantity,price):""":param product: 商品名称:param quantity: 商品数量:param price: 商品单价"""self.product = productself.quantity = quantityself.price = pricedef totol(self):""":return:订单总费用"""return self.quantity * self.price# 定义上下文(订单类)
class Order:def __init__(self,customer,cart,promotion=None):""":param customer: 顾客:param cart: 购物车:param promotion: 优惠策略"""self.customer = customerself.cart = cartself.promotion = promotiondef total(self):""":return:顾客订单打折之前的总费用"""if not hasattr(self,'__total'):self.__total = sum(item.totol() for item in self.cart)return self.__totaldef due(self):""":return:顾客最终支付的费用"""if self.promotion is None:return self.total()return self.total() - self.promotion(self)def __repr__(self):fmt = '<Order total: {:.2f} due: {:.2f}>'return fmt.format(self.total(), self.due())# 具体策略1:积分优惠策略
def FidelityPromo(order):"""如果积分大于1000,享受5%优惠"""if order.customer.fidelity > 1000:return order.total() * 0.05else:return 0# 具体策略2
def BulkItempromo(order):"""单个商品为20个及以上时,提供10%折扣"""discount = 0for item in order.cart:if item.quantity >= 10:discount += item.totol()* 0.1return discount# 具体策略3
def LargetOrderPromo(order):"""购物车中不同商品种类数量达到3个或以上提供7%折扣"""discount = 0# 获取购物车中所有不同的商品products = {item.product for item in order.cart}if len(products) >=3:discount += order.total() * 0.07return discountif __name__ == '__main__':#1. 策略1示例cus1 = Customer('Maple',2000)# 用户积分大于1000,享受5%优惠cart1=[Item('banana',20,2.0),Item('apple',10,1.0)]o1 = Order(cus1,cart1,FidelityPromo)print(o1) # <Order total: 50.00 due: 47.50> 47.5 =  (40 + 10 - 50 *0.05)# 2. 策略2示例cus2 = Customer('Jack',880)cart2= [Item('Book',30,1.0),Item('Radio',5,1.0)] #Book订单超过20个,提供10%折扣o2 = Order(cus2,cart2,BulkItempromo)print(o2)  # <Order total: 35.00 due: 32.00>  32.00 =  (30 -30 * 0.1) +  5# 策略3示例cus3 = Customer('Mick', 500)cart3 = [Item('Phone', 5, 2.0), Item('Water', 5, 1.0),Item('ring',20,2)] #购物车不同商品达到3个.提供7%折扣o3 = Order(cus3, cart3, LargetOrderPromo)print(o3)  # <Order total: 55.00 due: 51.15> 51.15> =  (40 + 10 - 50 *0.05)

4、策略模式函数写法-最优策略

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/1/27 11:34
# @Author  : Maple
# @File    : 03-策略模式函数写法-最优策略.py
# @Software: PyCharm"""
如何自动选择最优策略?
"""#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/1/27 11:25
# @Author  : Maple
# @File    : 02-策略模式函数写法.py
# @Software: PyCharm#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/1/27 9:48
# @Author  : Maple
# @File    : 01-策略模式传统写法.py
# @Software: PyCharm
from abc import ABC, abstractmethod
from collections import namedtuple# 顾客具名元组
Customer = namedtuple('Customer','name fidelity')# 定义商品类
class Item:def __init__(self,product,quantity,price):""":param product: 商品名称:param quantity: 商品数量:param price: 商品单价"""self.product = productself.quantity = quantityself.price = pricedef totol(self):""":return:订单总费用"""return self.quantity * self.price# 定义上下文(订单类)
class Order:def __init__(self,customer,cart,promotion=None):""":param customer: 顾客:param cart: 购物车:param promotion: 优惠策略"""self.customer = customerself.cart = cartself.promotion = promotiondef total(self):""":return:顾客订单打折之前的总费用"""if not hasattr(self,'__total'):self.__total = sum(item.totol() for item in self.cart)return self.__totaldef due(self):""":return:顾客最终支付的费用"""if self.promotion is None:return self.total()return self.total() - self.promotion(self)def __repr__(self):fmt = '<Order total: {:.2f} due: {:.2f}>'return fmt.format(self.total(), self.due())# 具体策略1:积分优惠策略
def FidelityPromo(order):"""如果积分大于1000,享受15%优惠"""if order.customer.fidelity > 1000:return order.total() * 0.15else:return 0# 具体策略2
def BulkItemPromo(order):"""单个商品为20个及以上时,提供10%折扣"""discount = 0for item in order.cart:if item.quantity >= 10:discount += item.totol()* 0.1return discount# 具体策略3
def LargetOrderPromo(order):"""购物车中不同商品种类数量达到3个或以上提供7%折扣"""discount = 0# 获取购物车中所有不同的商品products = {item.product for item in order.cart}if len(products) >=3:discount += order.total() * 0.07return round(discount,2)# 最优策略
def optimization_strategy(order):""":param order: 订单类:return:最优策略和最大折扣"""# 手动定义所有优惠策略promos = [FidelityPromo,BulkItemPromo,LargetOrderPromo]p_final =  Nonediscount_final = 0for p in promos:discount = p(order)if discount > discount_final:discount_final = discountp_final = preturn (p_final,discount_final)# 最优策略-获取当前模块所有策略的另外一种方式
def optimization_strategy2(order):# globals返回一个字典,表示当前的全局符号表promos = [globals()[name] for name in globals()if name.endswith('Promo')]p_final = Nonediscount_final = 0for p in promos:discount = p(order)if discount > discount_final:discount_final = discountp_final = preturn (p_final, discount_final)if __name__ == '__main__':#1. 最优策略示例1cus1 = Customer('Maple',2000)# 用户积分大于1000,享受15%(注意:为了测试,数值从5%调整到15%)优惠cart1=[Item('banana',20,2.0),Item('apple',10,1.0)]o1 = Order(cus1,cart1,FidelityPromo)print(optimization_strategy(o1)) # (<function FidelityPromo at 0x000001C46A4D8DC0>, 7.5)print(optimization_strategy2(o1)) # (<function FidelityPromo at 0x000001C46A4D8DC0>, 7.5)print('=====================================================')# 2. 最优策略示例2cus2 = Customer('Jack',880)cart2= [Item('Book',30,1.0),Item('Radio',5,1.0)] #Book订单超过20个,提供10%折扣o2 = Order(cus2,cart2,BulkItemPromo)print(optimization_strategy(o2)) # (<function BulkItemPromo at 0x0000018BF0F041F0>, 3.0)print(optimization_strategy2(o2)) # (<function BulkItemPromo at 0x00000233DF99E1F0>, 3.0)print('=====================================================')# 3. 最优策略示例3cus3 = Customer('Mick', 300)cart3 = [Item('Phone', 5, 2.0), Item('Water', 5, 1.0),Item('ring',8,2)] #购物车不同商品达到3个.提供7%折扣o3 = Order(cus3, cart3, LargetOrderPromo)print(optimization_strategy(o3))  # (<function LargetOrderPromo at 0x0000024CEE094280>, 2.17)print(optimization_strategy2(o3)) # (<function LargetOrderPromo at 0x00000233DF99E280>, 2.17)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/652138.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++ QT 信号的个人理解 信号就是独立文件调用的一种“协议”

一. 简介 就我个人来理解&#xff0c;信号槽机制与Windows下消息机制类似&#xff0c;消息机制是基于回调函数&#xff0c;Qt中用信号与槽来代替函数指针&#xff0c;使程序更安全简洁。 信号和槽机制是 Qt 的核心机制&#xff0c;可以让编程人员将互不相关的对象绑定在一起&a…

如何用web界面打开华为防火墙

目录 1.创建一个虚拟网卡 2.cloud操作 3.防火墙上操作 4. 登录 1.创建一个虚拟网卡 2.cloud操作 3.防火墙上操作 4. 登录

Netty的解码器和编码器

链路图 一个完整的RPC请求中&#xff0c;netty对请求数据和响应数据的处理流程如下图所示 网络线路中传输的都是二进制数据&#xff0c;之后netty将二进制数据解码乘POJO对象&#xff0c;让客户端或者服务端程序处理。 解码的工具称为解码器&#xff0c;是一个入站处理器InBo…

物联网协议Coap之C#基于Mozi的CoapClient调用解析

目录 前言 一、CoapClient相关类介绍 1、CoapClient类图 2、CoapClient的设计与实现 3、SendMessage解析 二、Client调用分析 1、创建CoapClient对象 2、实际发送请求 3、Server端请求响应 4、控制器寻址 总结 前言 在之前的博客内容中&#xff0c;关于在ASP.Net Co…

node.js 分布式锁看这篇就够用了

Redis SETNX 命令背后的原理探究 当然&#xff0c;让我们通过一个简单的例子&#xff0c;使用 Redis CLI&#xff08;命令行界面&#xff09;来模拟获取锁和释放锁的过程。 在此示例中 获取锁: # 首先&#xff0c;设置锁密钥的唯一值和过期时间(秒) 127.0.0.1:6379> SET …

数字三角形(很经典的动态规划问题)

给定一个如下图所示的数字三角形&#xff0c;从顶部出发&#xff0c;在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点&#xff0c;一直走到底层&#xff0c;要求找出一条路径&#xff0c;使路径上的数字的和最大。 73 88 1 02 7 4 4 4 5 2 6 …

第2章-神经网络的数学基础——python深度学习

第2章 神经网络的数学基础 2.1 初识神经网络 我们来看一个具体的神经网络示例&#xff0c;使用 Python 的 Keras 库 来学习手写数字分类。 我们这里要解决的问题是&#xff0c; 将手写数字的灰度图像&#xff08;28 像素28 像素&#xff09;划分到 10 个类别 中&#xff08;0…

基于多种CNN模型在清华新闻语料分类效果上的对比

该实验项目目录如图&#xff1a; 1、 模型 1.1. TextCNN # coding: UTF-8 import torch import torch.nn as nn import torch.nn.functional as F import numpy as npclass Config(object):"""配置参数"""def __init__(self, dataset, embedd…

【C++类与对象(上)】

C类与对象(上&#xff09; 1.面向过程和面向对象初步认识2.类的引入3.类的定义4.类的访问限定符及封装4.1 访问限定符4.2 封装 5.类的作用域6.类的实例化7.类的对象大小的计算7.1如何计算类对象的大小7.2 类对象的存储方式猜测7.3结构体内存对齐规则 8.类成员函数的this指针8.1…

Java多线程基础-18:线程安全的集合类与ConcurrentHashMap

Java标准库提供了很多集合类&#xff0c;但有一些集合类是线程不安全的&#xff0c;也就是说&#xff0c;在多线程环境下可能会出问题的。常用的ArrayList&#xff0c;LinkedList&#xff0c;HashMap&#xff0c;PriorityQueue等都是线程不安全的&#xff08;Vector, Stack, Ha…

Android创建工程

语言选择Java&#xff0c;我用的Java 最小SDK&#xff1a;就是开发的APP支持的最小安卓版本 Gradle 是一款Google 推出的基于 JVM、通用灵活的项目构建工具&#xff0c;支持 Maven&#xff0c;JCenter 多种第三方仓库;支持传递性依赖管理、废弃了繁杂的xml 文件&#xff0c;转而…

关于ArcGIS的Update更新工具的疑问

Update更新工具官方帮助文件解释如下&#xff1a; 但是根据这个插图很让人疑惑&#xff0c;输入要素是蓝色&#xff0c;更新要素是黄色&#xff0c;输出要素为绿色&#xff0c;而且全部是绿色。我一直以为是与更新要素相交&#xff08;被包含切割&#xff09;的哪些输入要素都被…

【常用工具】7-Zip 解/压缩软件——基本使用方法

在实际日常工作或项目中&#xff0c;经常会遇到需要在window操作系统上压缩文件&#xff0c;在Linux操作系统上解压缩的场景&#xff0c;一款实用的压缩软件迫在眉睫&#xff0c;经过实际使用总结&#xff0c;7-Zip可以很好的解决很多压缩和解压缩问题&#xff0c;其基本使用方…

WordPress如何自定义日期和时间格式?附PHP日期和时间格式字符串

WordPress网站在很多地方都需要用到日期和时间&#xff0c;那么我们应该在哪里设置日期和时间呢&#xff1f;又如何自定义日期和时间格式呢&#xff1f;下面boke112百科就跟大家一起来学习一下PHP标准化的日期和时间格式字符串。 特别说明&#xff1a;格式字符是标准化的&#…

canvas绘制旋转的大风车

查看专栏目录 canvas实例应用100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

LCweekly-game

ExScorecomplete situation1220717/719(解答错误)30523/537(超时,弱智题已AC)40 有用的是Ex2和Ex4 Ex2 my solution class Solution { public://calculate xs l-time 幂乘int jiecheng(int x,int l){int zx;for(int i0;i<l;i){if(z>pow(10,4.5))return 0;zz*z;}return…

C#算法(11)—求三个点构成圆的圆心坐标和半径

前言 我们在上位机开发领域也经常会碰到根据三个点求出圆的圆形、半径等信息的场景,本文就是详细的介绍如何根据三个点使用C#代码求出三点构成的圆的圆心坐标、圆半径、三点构成的圆弧的角度。 1、3点求圆分析 A、B、C三个点都是圆上的坐标点,过向量AB做中垂线,过向量AC做…

What is `@Scheduled` does?

Scheduled 是Spring框架中用于定时任务调度的注解&#xff0c;它允许我们在类的方法上声明一个方法作为定时任务&#xff0c;由Spring容器统一管理和执行。使用此注解后&#xff0c;Spring会根据注解中的属性配置&#xff0c;按照指定的时间规则自动调用该方法。 public class…

文心一言 VS ChatGPT :谁是更好的选择?

前言 目前各种大模型、人工智能相关内容覆盖了朋友圈已经各种媒体平台&#xff0c;对于Ai目前来看只能说各有千秋。GPT的算法迭代是最先进的&#xff0c;但是它毕竟属于国外产品&#xff0c;有着网络限制、注册限制、会员费高昂等弊端&#xff0c;难以让国内用户享受。文心一言…

2023年度AI盘点 AIGC|AGI|ChatGPT|人工智能大模型

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 2023年是人工智能大语言模型大爆发的一年&#xff0c;一些概念和英文缩写也在这一年里集中出现&#xff0c;很容易混淆&#xff0c;甚至把人搞懵。 文章目录 前言01 《ChatGPT 驱动软件开…