Python Cookbook-6.5 继承的替代方案——自动托管
任务
你需要从某个类或者类型继承,但是需要对继承做一些调整。比如,需要选择性地隐藏某些基类的方法,而继承并不能做到这一点。
解决方案
继承是很方便的,但它并不是万用良药。比如,它无法让你隐藏基类的方法或者属性。而自动托管技术则提供了一种很好的选择。假设需要把一些对象封起来变成只读对象从而避免意外修改的情况。那么,除了禁止属性设置的功能,还需要隐藏修改属性的方法。下面我们给出一个办法:
#同时支持2.3和2.4
try:set
except NameError:from sets import Set as set
class ROError(AttributeError):pass
class Readonly:#这里并没有用继承,我们会在后面讨论其原因mutators = {list:set('''__delitem__ __delslice__ __iadd__ __imul____setitem__ __setslice__ __append extend insert pop remove sort'''.split()),dict:set('''__delitem__ __setitem__ clear pop popitemsetdefault update'''.split()),}def __init__(self,o):object.__setattr__(self,'_o',o)object.__setattr__(self,'_no',self.mutators.get(type(o),()))def __setattr__(self,n,y):raise ROError,"Can't set attr %r on RO obiect" %n def __delattr__(self,n):raise ROError,"Can't del attr %r from Ro object" %n def __getattr__(self,n):if n in self._no:raise ROError,"Can't get attr %r from Ro object" %nreturn getattr(self._o, n)
通过修改 mutators,即 Readonly.mutators[sometype] = the_mutators,还可以轻松地增加其他需要处理的类型。
讨论
自动托管是一种强大而通用的技术。在本节的例子中,通过使用这个技术我们能得到和类继承几乎完全一样的效果,同时还能隐藏一些名字。我们在任务中使用这个模拟的子类将一些对象封装起来,使之变成只读对象。它的性能也许不如真正的继承,但另一方面,作为补偿,我们获得了更好的灵活度和更精细的粒度控制。
基本的想法是,我们的类的每个实例都含有我们想要封装的类型的实例。每当客户代码试图从我们的类的实例中获取属性时,除非该属性已经在类中被定义了(比如定义在 Readonly类的 mutators 字典中),否则__getattr__ 在完成检查之后,会透明地将这个请求转交给被封装的实例。在Python中,方法同样也是属性,访问的方式也一样,所以无论是访问方法还是属性,代码无须改变。用来访问属性的__getattr__方法同时也可用于访问方法。
解决方案的注释没有解释不使用继承的原因,这里我们会给出一点解释。这种基于__getattr__的方式也可用于特殊方法,但仅对旧风格类的实例有效。在新的对象模型中,Python 操作直接通过类的特殊方法来进行,而不是实例的。关于这个问题的更多内容可以在 6.6 节和 20.8节中看到。本节采用的方案——让 Readonly 类成为旧风格类,从而避开这个问题,并把相关内容留到其他章节——在真实的生产代码中是不值得推荐的。我在这里用仅仅是为了控制篇幅,同时避免重复其他章节的内容。
setattr__的角色类似于__getattr,当客户代码设置实例的属性时,它就会被调用,这个任务要求某些属性为只读,我们只需简单地禁止属性访问操作即可。记住,要在方法的代码编写中避免激发对__setattr__的调用,在有__setattr__的类的方法中你不应该使用self.n = v这样的语句。最简单的是直接把设置操作委托给类object,如同类Readonly在它的__init__ 方法中所做的那样。方法__delattr__完成了最后拼图,它会处理那些试图从实例中删除属性的操作。
以自动托管方式完成的封装并不适用于采用了类型检查的客户代码或者框架代码。在那种情况下,客户代码或框架代码完全破坏了多态性,代码本身应该是被重写的。记住不要在你自己的代码中使用类型检查,因为你可能根本无须那么做。见6.13节提供的更好的选择。
在 Python 的老版本中,自动托管的流行程度甚至比现在还高,那是因为当时 Python 不支持从内建的类型继承。而对于现在的 Python,从内建类型继承是允许的,因此自动托管就用得不那么频繁了。不过,自动托管仍然具有它的地位——它只是稍微远离了聚光灯一点点。托管比继承更加灵活,而有时这种灵活是无价的。除了选择性地托管(从而高效地实现了某些属性的“隐藏”),一个对象还可以在不同的时间托管给不同的子对象,或者一次托管给多个子对象,继承无法提供任何能够与之相比的特性。下面给出托管给多个特定子对象的例子。假设你有个类,提供各种“转发方法”,比如:
class Pricing(object):def __init__(self,location,event):self.location = locationself.event = eventdef setlocation(self,location):self.location = locationdef getprice(self):return self.location.getprice()def getquantity(self):return self.location.getquantity()def getdiscount(self):return self.event.getdiscount()and many more such methods
继承很明显不适用,因为 Pricing的实例需要托管给特定的location和event实例,这些实例在初始化阶段传入而且可能会被修改。自动托管的补救方法是:
class AutoDelegator(object):delegates = ()do_not_delegate = ()def __getattr__(self,key):if key not in self.do_not_delegate:for d in self.delegates:try:return getattr(d,key)except AttributeError:passraise AttributeError,key
class Pricing(AutoDelegator):def __init__(self,location,event):self.delegates = [location,event]def setlocation(self,location):self.delegates[0] = location
在此例中,我们没有托管属性的删除和设置,而只是托管了属性的获取(还有一些非特殊方法)。当然,这个方式只有在我们想要托管的各个对象的方法(以及其他属性)不会互相干扰的情况下才会充分有效,比如,location最好不要有个getdiscount方法否则它会抢先进行方法的托管,而此方法原本应该是由event对象来执行的。
如果一个需要大量托管的类涉及这种问题,它可以简单地定义一些对应的方法,这是因为只有在用别的方式无法找到属性和方法时,__getattr__才会介入。而通过do_not_delegate 属性还可以隐藏托管对象的一些属性和方法,而且它也可以被子类改写。举个例子,如果类 Pricing 想要隐藏一个叫做 setdiscount 的方法,此方法由 event提供,做一点点修改就可以了:
class Pricing(AutoDelegator):
do_not_delegate = ('set_discount')
其余部分则与前面代码片段相同。
相关文章:
Python Cookbook-6.5 继承的替代方案——自动托管
任务 你需要从某个类或者类型继承,但是需要对继承做一些调整。比如,需要选择性地隐藏某些基类的方法,而继承并不能做到这一点。 解决方案 继承是很方便的,但它并不是万用良药。比如,它无法让你隐藏基类的方法或者属…...
【深度学习与大模型基础】第9章-条件概率以及条件概率的链式法则
简单理解条件概率 条件概率就是在已知某件事发生的情况下,另一件事发生的概率。用数学符号表示就是: P(A|B) 在B发生的前提下,A发生的概率。 计算机例子:垃圾邮件过滤 假设你写了一个程序来自动判断邮件是否是垃圾邮件…...
STM32-FreeRTOS的详细配置
配置FreeRTOS 原文链接:https://ydamooc.github.io/posts/c9defcd/ 1.1 下载FreeRTOS 打开FreeRTOS官网:https://www.freertos.org/ 点击下载,并且选择"FreeRTOS 202212.01"版本,再点击Download按钮下载官方的资源包…...
行为检测技术指南
以下是行为检测技术的全面技术指南,涵盖核心技术原理、应用场景及发展趋势: 一、核心行为检测技术分类 1. 基于计算机视觉的行为检测 目标检测算法 通过目标定位与分类识别行为,典型算法包括: YOLO系列(YOLOv5/v8):实时性强,适用于视频流中的动作识别(如摔倒、抽烟检…...
视觉自回归图像生成:基于多模态大模型的万字深度梳理
目前利用多模态大模型进行图像生成主要有以下两种形式: LLM作为condtioner:利用MLLM依据用户输入的text prompt来生成条件信息,条件信息被注入到下游生成模型进行更精细化的生成控制。这种形式通常需要外接一个额外专门的多模态生成模型&…...
openssh离线一键升级脚本分享(含安装包)
查看当前的版本 [rootmyoracle ~]#ssh -V相关安装包下载地址 openssh下载地址:http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssl下载地址:https://www.openssl.org/source/zlib下载地址:http://www.zlib.net/今天演示从7.4升级…...
音视频之H.265/HEVC预测编码
H.265/HEVC系列文章: 1、音视频之H.265/HEVC编码框架及编码视频格式 2、音视频之H.265码流分析及解析 3、音视频之H.265/HEVC预测编码 预测编码是视频编码中的核心技术之一。对于视频信号来说,一幅图像内邻近像素之间有着较强的空间相关性,相邻图像之…...
Python异步编程入门:Async/Await实战详解
引言 在当今高并发的应用场景下,传统的同步编程模式逐渐暴露出性能瓶颈。Python通过asyncio模块和async/await语法为开发者提供了原生的异步编程支持。本文将手把手带你理解异步编程的核心概念,并通过实际代码案例演示如何用异步爬虫提升10倍效率&#…...
设计模式每日硬核训练 Day 13:桥接模式(Bridge Pattern)完整讲解与实战应用
🔄 回顾 Day 12:装饰器模式小结 在 Day 12 中,我们学习了装饰器模式(Decorator Pattern): 强调在不改变原类结构的前提下,动态为对象增强功能。通过“包装对象”实现运行时组合,支…...
库洛游戏一面+二面
目录 一面 1. ArrayList和LinkedList的区别,就是我在插入和删除的时候他们在时间复杂度上有什么区别 2. hashmap在java的底层是怎么实现的 3. 红黑树的实现原理 4. 红黑树的特点 5. 为什么红黑树比链表查询速度快 6. 在java中字符串的操作方式有几种 7. Stri…...
前端面试-Vue篇
核心概念 Vue 3的响应式原理与Vue 2有何本质区别?Vue中虚拟DOM的diff算法优化策略有哪些?Vue组件间通信方式有哪些?适用场景分别是什么?Vue的生命周期钩子在Composition API中如何替代?Vue的模板编译过程是怎样的&…...
XSS攻击(反射型、存储型、dom型、PDF、SWF、SVG)
一、XSS攻击是什么 XSS是恶意攻击者往 Web 页面里插入恶意可执行网页脚本代码,当用户浏览该页之时,嵌入其中 Web 里面的脚本代码会被执行,从而可以达到攻击者盗取用户信息或其他侵犯用户安全隐私的目的。 二、XSS分类 反射型XSS 常见情况是…...
C复习(主要复习)
指针和数组 指针数组是一个数组,数组的每个元素都是指针。它适用于需要存储多个指针的场景,如字符串数组。数组指针是一个指针,指向一个数组。它适用于需要传递整个数组给函数或处理多维数组的场景。 函数指针:函数指针的定义需要…...
Python及C++中的集合
1. Python 中的集合(set) 1.1 特性 无序性:集合中的元素没有顺序,不能通过索引访问。唯一性:集合中的元素不能重复,如果尝试添加重复的元素,集合会自动忽略。可变性:集合是可变的&…...
Ubuntu24.04搭建ESP8266_RTOS_SDK V3.4开发环境
【本文发布于https://blog.csdn.net/Stack_/article/details/147194686,未经允许不得转载,转载须注明出处】 需要有Linux使用基础,自行准备 1、VM17 Pro (自行搜索教程安装) 2、ubuntu-24.04-desktop-amd64 ࿰…...
数据仓库分层存储设计:平衡存储成本与查询效率
数据仓库分层存储不仅是一个技术问题,更是一种艺术:如何在有限的资源下,让数据既能快速响应查询,又能以最低的成本存储? 目录 一、什么是数据仓库分层存储? 二、分层存储的体系架构 1. 数据源层(ODS,Operational Data Store) 2. 数据仓库层(DW,Data Warehouse)…...
matlab求和∑函数方程编程?
matlab求和∑函数方程编程? 一 题目:求下列函数方程式的和 二:代码如下: >> sum_result 0; % 初始化求和变量 for x 1:10 % 设…...
基于Java+MySQL实现的(Web)科研资讯推送系统
科研资讯推送系统 技术选型 核心框架:SpringBoot 数据库层:springdatajpa 安全框架:Shiro 数据库连接池:Druid 缓存:Ehcache 部署 阿里云学生机:ecs.n4.small Tomcat:9.0 JDK:1.8 数据库:MySQL8.0 操作系统:CentOS…...
PHP弱类型hash比较缺陷
目录 0x00 漏洞原因 0x01 利用方法 0x02 [BJDCTF2020]Easy MD5 1 利用md5($password,true)实现SQL注入 PHP md5弱类型比较 数组绕过 0x00 漏洞原因 1、在进行比较的时候,会先将两边的变量类型转化成相同的,再进行比较 2、0e在比较的时候会将其认…...
asm汇编源代码之-汉字点阵字库显示程序源代码下载
汉字点阵字库显示程序 源代码下载 文本模式下显示16x16点阵汉字库内容的程序(标准16x16字库需要使用CHGHZK转换过后才能使用本程序正常显示) 本程序需要调用file.asm和string.asm中的子程序,所以连接时需要把它们连接进来,如下 C:\> tlink showhzk file string 调用参…...
Excel 中让表格内容自适应列宽和行高
Excel 中让表格内容自适应列宽和行高 目录 Excel 中让表格内容自适应列宽和行高自适应列宽自适应行高在Excel中让表格内容自适应列宽和行高,可参考以下操作: 自适应列宽 方法一:手动调整 选中需要调整列宽的列(如果是整个表格,可点击表格左上角行号和列号交叉处的三角形全…...
从 Vue 到 React:深入理解 useState 的异步更新
目录 从 Vue 到 React:深入理解 useState 的异步更新与函数式写法1. Vue 的响应式回顾:每次赋值立即生效2. React 的状态更新是异步且批量的原因解析 3. 函数式更新:唯一的正确写法4. 对比 Vue vs React 状态更新5. React useState 的核心源码…...
Java使用ANTLR4对Lua脚本语法校验
文章目录 什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Grammar文件maven配置生成Lexer Parser Listener Visitor代码新建实体类Lua语法遍历器语法错误监听器单元测试 参考 什么是ANTLR? https://www.antlr.org/ ANTLR (ANothe…...
vue3.2 + element-plus 实现跟随input输入框的弹框,弹框里可以分组或tab形式显示选项
效果 基础用法(分组选项) 高级用法(带Tab栏) <!-- 弹窗跟随通用组件 SmartSelector.vue --> <!-- 弹窗跟随通用组件 --> <template><div class"smart-selector-container"><el-popove…...
Vue 2.0和3.0笔记
Vue 3 关于组件 今天回顾了下2.0关于组件的内容,3.0定义组件的方式多了一种就是通过单文件组件(Single-File Component)的方式将Vue的模板,逻辑和样式放到一个文件中,2.0则不同,它是将模板放到一个属性中…...
Windows VsCode Terminal窗口使用Linux命令
背景描述: 平时开发环境以Linux系统为主,有时又需要使用Windows系统下开发环境,为了能像Linux系统那样用Windows VsCode,Terminal命令行是必不可少内容。 注:Windows11 VsCode 1.99.2 下面介绍,如何在V…...
负载均衡的实现方式有哪些?
负载均衡实现方式常见的有: 软件负载均衡、硬件负载均衡、DNS负载均衡 扩展 二层负载均衡:在数据链路层,基于MAC地址进行流量分发,较少见于实际应用中 三层负载均衡:在网络层,基于IP地址来分配流量,例如某…...
Oracle 中的 NOAUDIT CREATE SESSION 命令详解
Oracle 中的 NOAUDIT CREATE SESSION 命令详解 NOAUDIT CREATE SESSION 是 Oracle 数据库中用于取消对用户登录会话审计的命令,它与 AUDIT CREATE SESSION 命令相对应。 一、基本语法 NOAUDIT CREATE SESSION [BY user1 [, user2]... | BY [SESSION | ACCESS]] …...
OutputStreamWriter 终极解析与记忆指南
OutputStreamWriter 终极解析与记忆指南 一、核心本质 OutputStreamWriter 是 Java 提供的字符到字节的桥梁流,属于 Writer 的子类,负责将字符流按指定编码转换为字节流。 注意:OutputStreamWriter也是一个字符流,也是一个转换…...
1022 Digital Library
1022 Digital Library 分数 30 全屏浏览 切换布局 作者 CHEN, Yue 单位 浙江大学 A Digital Library contains millions of books, stored according to their titles, authors, key words of their abstracts, publishers, and published years. Each book is assigned an u…...
