python包装与授权

news2024/11/27 13:32:08

在这里插入图片描述

欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起学习和分享Linux、C、C++、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。


包装与授权

    • 包装
    • 授权
    • \_\_setattr__,\_\_delattr\_\_,\_\_getattr\_\_
    • \_\_getattribute__
    • 618图书推荐


专栏:《python从入门到实战》


所有便准数据类型都可以通过两种方式产生,一种是直接定义,一种是使用相应的函数,比如要产生字符串,可以s=’hello’或s=str(hello)。像str这种函数都是工厂函数,实际上工厂函数都是类,我们可以通过继承这些类来定制自己的数据类型。(包装)

包装

python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了继承/派生知识(其他的标准类型均可以通过下面的方式进行二次加工)。

二次加工标准类型(基于继承实现)

class List(list): #继承list所有的属性,也可以派生出自己新的,比如append和mid
    def append(self, p_object):
        ' 派生自己的append:加上类型检查'
        if not isinstance(p_object,int): #if type(p_object) is int:
            raise TypeError('must be int')
        #self.append(p_object) #死循环
        #list.append(self, p_object) #调用父类的方法
super().append(p_object) #调用父类的方法

    @property
    def mid(self):
        '新增自己的属性'
        index=len(self)//2
        return self[index]

l=List([1,2,3,4])
print(l)
l.append(5)
print(l)
# l.append('1111111') #报错,必须为int类型

print(l.mid)

#其余的方法都继承list的
l.insert(0,-123)
print(l)
l.clear()
print(l)

clear加权限限制

class List(list):
    def __init__(self,item,tag=False):
        super().__init__(item)
        self.tag=tag
    def append(self, p_object):
        if not isinstance(p_object,str):
            raise TypeError
        super().append(p_object)
    def clear(self):
        if not self.tag:
            raise PermissionError
        super().clear()

l=List([1,2,3],False)
print(l)
print(l.tag)

l.append('saf')
print(l)

# l.clear() #异常

l.tag=True
l.clear()

授权

授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。
授权是采用已存在的功能达到最大限度的代码重用。在包装中我们可以新建、修改或删除已有的功能,授权的过程就是将更新的功能交由新类来处理,已存在的功能就授权给对象的默认属性。
实现授权的关键点就是覆盖__getattr__方法 (包装是通过继承实现)。在代码里包含一个对getattr()内建函数的调用,调用getattr()得到默认对象的属性(数据属性或者方法)并返回它,以便于访问或者调用。
当引用一个属性时,解释器首先会在局部名称空间中查找那个名字,比如一个自定义的方法或局部实例属性。如果没有在局部字典中找到,则搜索类名称空间,以防一个类属性被访问。最后,如果两类搜索都失败了,搜索则对原对象开始授权请求,此时__getattr__()会被调用。

示例1

import time
class FileHandle:
    def __init__(self,filename,mode='r',encoding='utf-8'):
        self.file=open(filename,mode,encoding=encoding)
    def write(self,line): #定制自己的write方法 – 对写入的内容加上时间
        t=time.strftime('%Y-%m-%d %T')
        self.file.write('%s %s' %(t,line))

    def __getattr__(self, item):
        return getattr(self.file,item)# self.file是通过系统默认的open获取的,它包含了默认open的所有方法,item是一个字符串,getattr以字符串形式调用方法

f1=FileHandle('b.txt','w+')
f1.write('你好啊')
f1.seek(0)
print(f1.read()) 
f1.close()

在实例和类FileHandle中都没有找到该属性,所以触发__getattr__先找f1的属性字典,没有则找类FileHandle的属性字典,没有则触发__getattr__,__getattr__中调用的是系统open返回的文件描述符的方法,通过自己的类实例化,调用系统的方法。

示例2

#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
#我们来加上b模式支持
import time
class FileHandle:
    def __init__(self,filename,mode='r',encoding='utf-8'):
        if 'b' in mode:
            self.file=open(filename,mode)
        else:
            self.file=open(filename,mode,encoding=encoding)
        self.filename=filename
        self.mode=mode
        self.encoding=encoding

    def write(self,line):
        if 'b' in self.mode:
            if not isinstance(line,bytes):
                raise TypeError('must be bytes')
        self.file.write(line)

    def __getattr__(self, item):
        return getattr(self.file,item)

    def __str__(self):
        if 'b' in self.mode:
            res="<_io.BufferedReader name='%s'>" %self.filename
        else:
            res="<_io.TextIOWrapper name='%s' mode='%s' encoding='%s'>" %(self.filename,self.mode,self.encoding)
        return res
f1=FileHandle('b.txt','wb')
# f1.write('你好啊啊啊啊啊') #自定制的write,不用在进行encode转成二进制去写了
f1.write('你好啊'.encode('utf-8'))
print(f1)
f1.close()

示例3

class List:
    def __init__(self,seq):
        self.seq=seq

    def append(self, p_object):
        ' 派生自己的append加上类型检查,覆盖原有的append'
        if not isinstance(p_object,int):
            raise TypeError('must be int')
        self.seq.append(p_object)

    @property
    def mid(self):
        '新增自己的方法'
        index=len(self.seq)//2
        return self.seq[index]

    def __getattr__(self, item):
        return getattr(self.seq,item)

    def __str__(self):
        return str(self.seq)

l=List([1,2,3])
print(l)
l.append(4)
print(l)
# l.append('3333333') #报错,必须为int类型

print(l.mid)

#基于授权,获得insert方法
l.insert(0,-123)
print(l)

示例4

class List:
    def __init__(self,seq,permission=False):
        self.seq=seq
        self.permission=permission
    def clear(self):
        if not self.permission:
            raise PermissionError('not allow the operation')
        self.seq.clear()

    def __getattr__(self, item):
        return getattr(self.seq,item)

    def __str__(self):
        return str(self.seq)
l=List([1,2,3])
# l.clear() #此时没有权限,抛出异常


l.permission=True
print(l)
l.clear()
print(l)

#基于授权,获得insert方法
l.insert(0,-123)
print(l)

__setattr__,__delattr__,__getattr__

class Foo:
    x=1
    def __init__(self,y):
        self.y=y

    def __getattr__(self, item):
        print('----> from getattr:你找的属性不存在')


    def __setattr__(self, key, value):
        print('----> from setattr')
        # self.key=value #这就无限递归了,因为设置属性会触发__setattr__
        # self.__dict__[key]=value #应该使用它,直接修改底层字典

    def __delattr__(self, item):
        print('----> from delattr')
        # del self.item #无限递归了
        self.__dict__.pop(item)# 直接在底层字典删除,就不会触发了

#__setattr__添加/修改属性会触发它的执行
f1=Foo(10)
print(f1.__dict__) # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
f1.z=3
print(f1.__dict__)

#__delattr__删除属性的时候会触发
f1.__dict__['a']=3#我们可以直接修改属性字典,来完成添加/修改属性的操作
del f1.a
print(f1.__dict__)

#__getattr__只有在使用点调用属性且属性不存在的时候才会触发
f1.xxxxxx

getattr(obj)相当于obj.__getattr__()
setattr(obj)相当于obj.__setattr__()
delattr(obj)相当于obj.__delattr__()

  • 类的内置attr属性,你不定义的话会用默认的,如果定义了则用自己定义的。
  • class.at 调用时触发:如果类class中属性at不存在,则触发__getattr__
  • del class.at删除时触发:删除类class的属性at时,触发__delattr__
  • class.at=1设置时触发:设置类class的属性at时,触发__setattr__

自己定义这三个函数,在相应操作时,就可以触发自己想要的逻辑。

class MyClass:
def __init__(self, name)
    self.name = name #触发__setattr__
def __getattr__(self, item) #默认的__getattr__是属性不存在则报错,我们修改后不报错,仅打印提示
    print(“attr [%s] not found” %item)
def __setattr__(self, k, v) #默认的setattr会把设置的属性加在属性字典,但是我们自定义的setattr什么也没做,属性字典不会增加属性
    print(set attr’, k, v)
    if tyoe(v) is str: #限制value只能以字符串的形式设置
        print(set)
        #self.k = v #再次触发__setattr__,进入死循环
        self.__dict__[k] = v.upper() 
#真正的设置 – 直接操作底层数据结构,在属性字典中添加
    else:
        print(not str)
def __delattr__(self, item)
    """ #自己控制-所有属性不可删除
    print(‘can not delete [%s]’ %item)
    pass
    """
    print(‘delete attr[%s]%item)
    #del self.item #触发__delattr__ 进入死循环
    self.__dict__.pop(item) #真正的删除

mc = MyClass(‘hello’) #实例化的时候会触发__init__
print(mc.name) #hello
print(mc.hhh) #触发__getattr__  mcself  hhhitem(字符串的形式)
mc.age = 18
mc.age =18#触发__setattr__  mcself  agek  ‘18’v
del mc.name #触发__delattr__  mcself  name item(字符串的形式)

__getattribute__

#__getattr__
class Foo:
    def __init__(self,x):
        self.x=x

    def __getattr__(self, item):
        print('执行的是我')
        # return self.__dict__[item]

f1=Foo(10)
print(f1.x)
f1.xxxxxx #不存在的属性访问,触发__getattr__
#__getattribute__ - 不管属性是否存在,都会触发
class Foo:
    def __init__(self,x):
        self.x=x

    def __getattribute__(self, item):
        print('不管是否存在,我都会执行')

f1=Foo(10)
f1.x
f1.xxxxxx

如果二者同时出现

#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'

class Foo:
    def __init__(self,x):
        self.x=x

    def __getattr__(self, item):
        print('执行的是我')
        # return self.__dict__[item]
    def __getattribute__(self, item):
        print('不管是否存在,我都会执行')
        raise AttributeError('哈哈') #抛出AttributeError异常–跳转到__getattr__

f1=Foo(10)
f1.x
f1.xxxxxx

当__getattribute__与__getattr__同时存在,只会执行__getattribute__,除非__getattribute__在执行过程中抛出异常AttributeError,系统默认的__getattribute__,如果查找的属性不存在,当抛出异常AttributeError的时候,会跳转到__getattr__,也就是说,只有抛出异常AttributeError的时候,才会执行__getattr__,其他情况下只会执行__getattribute__。系统提供的默认__getattribute__,当要查找的属性存在时,会在当前属性字典中返回属性,如果要找的属性不存在会抛出异常AttributeError,转到__getattr__去执行,__getattr__接收异常来避免程序崩溃,并执行定义好的逻辑。

618图书推荐

书籍是知识的海洋,计算机好书推荐
在这里插入图片描述
🔥🔥🔥618,清华社 IT BOOK 多得图书活动开始啦!活动时间为2023 年6 月7 日至6 月18 日,清华社为您精选多款高分好书,涵盖了 C++、Java、Python、前端、后端、数据库、算法与机器学习等多个IT 开发领域,适合不同层次的读者。全场5 折,扫码领券更有优惠哦!快来京东点击链接 IT BOOK多得查看详情吧!


在这里插入图片描述
在这里插入图片描述


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

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

相关文章

ai聊天对话工具哪种好用?这些ai对话聊天工具不要错过

在如今信息爆炸的时代&#xff0c;人工智能技术正在逐渐渗透到我们的生活和工作中。ai对话聊天技术作为其中的一项重要应用&#xff0c;吸引了越来越多的关注。但是&#xff0c;ai对话聊天技术并不是万能的&#xff0c;它需要一定的技巧和策略才能真正发挥其价值。那么&#xf…

CAN总线转串口

一、CAN总线在工程机械中的广泛应用 随着科技的进步和现代施工项目大型化的要求,新一代工程机械需要实现集成化操作和智能控制。CAN总线是国际上应用最广泛的现场总线之一。CAN总线以其高可靠性、实时性、无破坏仲裁、多主等特性&#xff0c;已广泛应用于工程机械中&#xff0c…

这里推荐几个前端动画效果网站

1. AnimistaAnimista 是一个 CSS 动画/转场库和在线工具。它有许多现成的 CSS 动画片段可以直接使用,也可以在线定制动画。 网站地址:Animista - On-Demand CSS Animations Library 2. Animate.cssAnimate.css 是一个免费的 CSS 动画库,里面有 Attention Seekers 、 Bouncing E…

【Java|多线程与高并发】线程安全问题以及synchronized使用实例

文章目录 1. 前言2. 线程安全问题演示3.线程安全问题的原因4.synchronized关键字5. 总结 1. 前言 Java多线程环境下&#xff0c;多个线程同时访问共享资源时可能出现的数据竞争和不一致的情况。 线程安全一直都是一个令人头疼的问题.为了解决这个问题,Java为我们提供了很多方式…

MySQL为什么有了redolog还需要double write buffer?

MySQL为什么有了redolog还需要double write buffer&#xff1f; 问题 我们知道MySQL InnoDB引擎使用redolog作为异常容灾恢复的机制&#xff0c;当MySQL进程发生异常退出、机器断电等&#xff0c;在重新启动时&#xff0c;使用redolog恢复。 OK&#xff0c;redolog是被MySQL…

进程同步与进程通信(#include <windows.h>)

目录 实验二 进程同步与进程通信 一、实验目的 二、实验内容 任务一、进程同步与互斥 任务二、进程通信 实验二 进程同步与进程通信 备注&#xff1a;大二&#xff08;下&#xff09;操作系统实验二 一、实验目的 掌握基本的同步与互斥算法&#xff0c;理解P&#xff…

移植蓝牙芯片后,PCM 无声音问题记录

背景:投影仪项目上的蓝牙模组本地已经验证ok,送到客户那里发现HFP打电话没声音。 1. 客户平台是3566,android 11的环境, 该环境下其他的模组是可以的 2. 在3566上安装QQ, 波通VOIP电话后, 无阴影, 3. 通过示波器接收pcm 无波形输出, 问题分析查证 1.查看HCI log ,…

【LeetCode热题100】打卡第17天:接雨水全排列旋转图像

文章目录 【LeetCode热题100】打卡第17天&#xff1a;接雨水&全排列&旋转图像⛅前言 接雨水&#x1f512;题目&#x1f511;题解 全排列&#x1f512;题目&#x1f511;题解 旋转图像&#x1f512;题目&#x1f511;题解 【LeetCode热题100】打卡第17天&#xff1a;接雨…

Elasticsearch 中文分词器

IK 分词器 我们在ES中最常用的中文分词器就是IK分词器&#xff0c;其项目地址为&#xff1a;https://github.com/medcl/elasticsearch-analysis-ik 下载安装 下载地址&#xff1a; https://github.com/medcl/elasticsearch-analysis-ik/releases 下载时注意和es的版本对应&a…

Network 之十二 iPXE 源码、编译过程、Linker tables 机制、移植新驱动、固件使用

最近&#xff0c;正在学习 iPXE 源码&#xff0c;于是开始各种 Google 查找 iPXE 的资料进行学习。以下就是学习过程中一些感觉比较重要的点&#xff0c;特此记录&#xff0c;以备后续查阅。 起源 上世纪 90 年代初&#xff0c;网卡开始在其扩展卡上包含启动 ROM&#xff0c;每…

2023-6-9-一天一种设计模式

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f4a5;&#x1f4a5;&#x1f4a5;欢迎来到&#x1f91e;汤姆&#x1f91e;的csdn博文&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f49f;&#x1f49f;喜欢的朋友可以关注一下&#xf…

当在浏览器截屏过曝时,应该采取的措施

一、问题来源 屏幕打开了HDR模式后&#xff0c;浏览器在截图的一瞬间出现色彩错误 正常情况如下&#xff1a; HDR截图过曝后如下&#xff1a; 二、解决方法 1. 关闭屏幕HDR模式 桌面右键显示设置关闭HDR选项 2. 修改浏览器选项 地址栏输入 edge://flags&#xff08;Edg…

【Spring框架】初识Spirng

目录 Spring是什么&#xff1f;什么是容器&#xff1f;什么是IoC&#xff1f;传统开发ioc 开发(控制反转式程序开发) DI(依赖注入) Spring是什么&#xff1f; Spring指的是Spring Framework(Spring框架)&#xff0c;它是一个开源框架&#xff0c;有着活跃而庞大的社区&#xf…

支持无线连接的头戴式耳机,双音腔结构很好听,雷柏VH800上手

平时在PC上玩游戏&#xff0c;除了键鼠一类的操控设备很重要之外&#xff0c;耳机等音频设备也很重要&#xff0c;我用的是头戴式耳机&#xff0c;这种耳机现在有无线版本&#xff0c;用起来很方便&#xff0c;而且延迟很低&#xff0c;可以带来更好的声画同步效果&#xff0c;…

在unity中如何使用chatGPT让虚拟IP动起来

1、导入chatGpt 解决AI智能回答 请根据上一篇文章进行导入&#xff1a;如何使用ChatGPT在unity中进行低代码快速开发&#xff1f;_向视科技&#xff0c;让您看见未来&#xff08;nbhctec&#xff09;的博客-CSDN博客 2、文本也有转换工具 可导入unity 插件-RT-Voice PRO 2.…

【回眸】Python入门(五)基础语法列表和词典:Python如何消灭重复性劳动

前言 本篇博客为填坑篇&#xff0c;这个系列的上一篇竟然是2021年的9月30更新的&#xff0c;离谱&#xff0c;差点就到断更两周年纪念日了&#xff0c;后续逐渐走向填坑的每一天&#xff0c;继续创作&#xff0c;希望这个系列的专栏文章能帮助到更多有需要的人。 列表 什么是列…

C++算法:有向无环图拓扑排序(领接链表)

文章目录 前言一、邻接表二、代码1、生成图2、出度、入度计算3、拓扑排序 总结 前言 前文有向无环图实现游戏技能树中我们使用了矩阵存储图的关系&#xff0c;可以称之为邻接矩阵。显然&#xff0c;链表也是可以实现的。在图结构入门一文中&#xff0c;我们也提到了链表存储的…

湖南大学OS-2020(另一张)期末考试解析

【特别注意】 答案来源于wolf以及网络 是我在备考时自己做的&#xff0c;仅供参考&#xff0c;若有不同的地方欢迎讨论。 【试卷评析】 这张卷子很老了&#xff0c;我不知道具体的年份&#xff0c;部分题目可能有用。如果仔细研究应该会有所收获。 【试卷与答案】 一、选…

机器学习 | 决策树 Decision Tree | 概念向

参考视频&#xff1a;【小萌五分钟】机器学习 | 决策树 文章目录 &#x1f4da;决策树是什么&#xff08;根节点、叶子节点、分支、深度&#xff09;&#x1f4da;决策树&#xff1a;分类树——算法思想&#x1f4da;分类错误率&#xff0c;熵&#xff0c;基尼指数&#x1f407…

蓝库云|实体店搭建一套巡店管理系统,能让大型连锁店立竿见影

传统巡店工作存在许多问题特别是大型连锁店&#xff0c;包括工作效率低、数据收集不便捷、信息共享困难等。为了解决这些问题&#xff0c;蓝库云认为拥有一套巡店管理系统就显得非常重要了。 巡店管理系统具备以下特点&#xff1a;手机电脑数据同步、实时数据采集和记录、可定…