python全栈学习记录(二十四)元类、异常处理

news2024/10/9 22:32:36

元类、异常处理

文章目录

  • 元类、异常处理
  • 一、元类
    • 1.元类控制类的实例化
    • 2.属性/方法的查找顺序
    • 3.单例
  • 二、异常处理

一、元类

1.元类控制类的实例化

类的__call__方法会在产生的对象被调用时自动触发,args和kwargs就是调用实例时传入的参数,返回值是调用实例以后的结果。

class A():
    def __call__(self, *args, **kwargs):
        print("from __call__")
        print(args,kwargs)
        return 333


a=A()
print(a(111,k=222))

<<<from __call__
<<<(111,) {'k': 222}
<<<333

一般情况下类的__call__函数会完成以下的几件事情:创建一个新对象、根据传入的值完成新对象的初始化、返回新建的对象。换句话说__new__和__init__两个方法是在__call__方法里面完成的。
基于此我们就可以通过复写元类的__call__方法完成对类实例化的控制效果。

class Mymeta(type):

    def __call__(self, *args, **kwargs):
        #因为是类调用的时候触发了__call__方法,所以此处的self是People
        # 1、先造出一个People的空对象
        #obj=object.__new__(self)
        obj=self.__new__(self)
        # 2、用People的初始化方法为新建的People对象完成初始化
        self.__init__(obj,*args,**kwargs)
        # 3、返回初始好的对象
        return obj


class People(object,metaclass=Mymeta):
    country='China'
    def __init__(self,name,age):
        self.name=name
        self.age=age


print(People('111',222))

<<< <__main__.People object at 0x0000022AFFB9AE80>

上述代码中当调用People(‘111’,222)时,触发元类的__call__方法,首先会调用People的__new__方法产生一个People类的新对象,由于People没有__new__方法,根据继承的机制解释器会去父类object中找,新对象产生后就需要根据People类的初始化方法完成对象的初始化,所以我们调用People的初始化方法并将新产生的obj对象传入完成初始化操作,最后返回这个obj对象也就完成了实例化的操作了。我们完全可以在__call__方法的内部添加一些功能已完成实例的定制,例如下面要讲到的单例。

2.属性/方法的查找顺序

python类的属性/方法的查找顺序为:

  • 先在对象层查找,当前对象找不到就去找父类(mro表)
  • 如果父类也找不到再去对象上一级查找(注意实例和类、类和元类都是跨一级的关系)
  • 但是属性/方法的查找最多只能跨一级(例如实例中调用属性,在对应类及其父类中找不到就结束了,因为实例到元类跨了两个级别,实例中调的属性无法去元类中查找)

根据上面的规则简单来讲就是:

  • 在实例中查找:实例——对应的类——对应类的父类
  • 在类中查找:类——父类——元类——元类的父类

python中继承和实例的关系如下:

  • type是所有类的元类、也是自己的元类
  • object是所有类的父类
  • int、str、list等是object的子类,是type的实例
  • 1、‘1’、[1]等是int、str、list的实例
  • class创建的类是type的实例,是object的子类

3.单例

单例模式:基于某种方法实例化多次得到实例是同一个。
当实例化多次得到的对象中存放的属性都一样的情况,应该将多个对象指向同一个内存地址以减少占用的空间。
例如现在我需要传入一个ip地址,我们自动最常用的ip是127.0.0.1,如果需要传入的是127.0.0.1那么就直接调用单例,如果是其他ip就创建新实例。这个需求可以有三种方法实现:

方式一:内置属性法

class Single:
    __instacne=None
    #默认的ip值
    __ip="127.0.0.1"

    def __init__(self,ip):
        self.ip=ip
	
	#使用默认的ip单例
    @classmethod
    def from_conf(cls):
        if cls.__instacne is None:
            cls.__instacne=cls(cls.__ip)
        return cls.__instacne

obj1=Single('127.10.0.10')
obj2=Single.from_conf()
obj3=Single.from_conf()
print(obj1,obj2,obj3)
<<< <__main__.Single object at 0x0000021A1F24AEB0> <__main__.Single object at 0x0000021A1F24ADF0> <__main__.Single object at 0x0000021A1F24ADF0>

方法二:装饰器

def singleton(cls):
    #闭包函数内存一个传默认值的实例
    cls.__instance=cls('127.0.0.1')
    def wrapper(*args,**kwargs):
        #不传值则返回存的单例
        if len(args) == 0 and len(kwargs) == 0:
            return cls.__instance
        return cls(*args,**kwargs)
    return wrapper

@singleton
class Single:
    def __init__(self,ip):
        self.ip=ip


obj1=Single('127.10.0.10')
obj2=Single()
obj3=Single()
print(obj1,obj2,obj3)
<<< <__main__.Single object at 0x000001F5E256AD60> <__main__.Single object at 0x000001F5E256AE80> <__main__.Single object at 0x000001F5E256AE80>

方法三:元类控制单例的产生

class Mymeta(type):
    #初始化类的过程需要传入class_name,class_bases,class_dic
    def __init__(self,class_name,class_bases,class_dic):
        #继承type的__init__方法初始化Single
        super(Mymeta,self).__init__(class_name,class_bases,class_dic )
        #由于Single需要一个内置属性存放单例,所以在初始化类的过程中完成单例的创建
        self.__instance = self.__new__(self)  # 造出一个Mysql的对象
        self.__init__(self.__instance, '127.0.0.1')

    def __call__(self, *args, **kwargs):
        #当实例化不传参时,返回单例,传参则正常完成实例化
        if len(args) == 0 and len(kwargs) == 0:
            return self.__instance
        obj=self.__new__(self)
        self.__init__(obj,*args,**kwargs)
        return obj

class Single(metaclass=Mymeta):
    def __init__(self,ip):
        self.ip=ip

obj1=Single('127.10.0.10')
obj2=Single()
obj3=Single()
print(obj1,obj2,obj3)
<<< <__main__.Single object at 0x000001CA60BFCAF0> <__main__.Single object at 0x000001CA60BFCC40> <__main__.Single object at 0x000001CA60BFCC40>

二、异常处理

当程序运行过程中出现错误时,就会报错,这个就是异常。如果我们希望代码在可能发生错误的情况下依然能正常运行,就需要用到异常处理。但是需要注意异常处理并不是越多越好,如果程序中的错误是可以预知的,应该尽可能不使用异常处理,只有当程序中的错误是不可预知的,才需要使用到异常处理。

异常处理的常用格式:

#当try中的程序运行出现错误时会跳转到except处,根据except后的信息处理错误
#except ValueError表示出现ValueError错误时出现跳转到except处运行下面的代码,如果出现其他错误则直接报错
try:
	代码块
except ValueError:
	代码块
#同时接受多个错误
except (IOError,NameError):
	代码块
#接受错误并打印错误信息
except ImportError as e:
	#e为错误信息
	print(e)
#except Exception表示接受所有的错误,Exception可以不写
except Exception:
	代码块

#else表示try中的代码没有异常时运行,finally表示try except代码运行完以后运行,通常用来回收资源
try:
	代码块
except:
	代码块
else:
	代码块
finally:
	代码块

常见的错误形式:
在这里插入图片描述

断言:

#assert会在不满足后面的条件时报错,一般用于测试阶段
l=[1,2]
assert len(l)==3
<<<AssertionError

raise:

#程序运行至raise处时会抛出后面的错误
raise ValueError('找不到值')
<<<ValueError: 找不到值

自定义异常:

#自定义的错误类必须继承BaseException类
class NagaException(BaseException):
    def __init__(self,data):
        self.data=data

    def __str__(self):
        return self.data

try:
    raise NagaException('自定义错误')
except NagaException as e:
    print(e)
<<<自定义错误

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

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

相关文章

Hotspot是什么?

Hotspot 简单来说&#xff0c;JVM的一种。 一、HotSpot 的官方定义 HotSpot 是 Oracle 公司开发的一个高性能的 Java 虚拟机&#xff08;JVM&#xff09;。它通过一系列先进的技术和优化手段&#xff0c;为 Java 应用程序提供高效的运行环境&#xff0c;实现了跨平台的代码执行…

文献下载/影响因子查询/文献检索/文献翻译平台推荐

文献下载平台 科研通 文献互助平台 - 科研通(AbleSci.com) 每天签到可领10积分&#xff0c;右上角求助文献&#xff0c;一篇10积分&#xff0c;基本实现免费下载。 尽量输入doi&#xff08;类似文献id&#xff09;&#xff0c;如果没有doi则输入标题作者摘要等信息&#xff0…

SpringBoot 整合JPA

spring data jpa JPA(java persistence api) JPA是Java Persistence API的简称&#xff0c;中文名Java持久层API&#xff0c;是JDK 5.0注解或XML描述对象&#xff0d;关系表的映射关系&#xff0c;并将运行期的实体对象持久化到数据库中。 [1] Sun引入新的JPA ORM规范出于两…

链表Set_LinkList(建立)

用单链保存集合元素&#xff0c;元素由键盘输入。输入以-1结束&#xff0c;将所建链表打印输出。 链表结构如下图所示&#xff1a; 提示&#xff1a; 1.链表中数据元素为整型&#xff0c;typedef int ElemType; 2.用结构体自定义链表结构Set_LinkList &#xff1b; 3.初始化链表…

【每日刷题】Day135

【每日刷题】Day135 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. LCR 011. 连续数组 - 力扣&#xff08;LeetCode&#xff09; 2. 【模板】二维前缀和_牛客题霸_牛客…

基于SSM的共享读书网站

文未可获取一份本项目的java源码和数据库参考。 1.1 题目背景 进入新时代&#xff0c;中国的经济建设和社会发展需要与之相适应的人力资源相匹配。如何提升人力资源的素养&#xff0c;是新时代中国持续发展亟待解决的问题[1]。阅读不失为其中一个有效的手段。有效有益的阅读能…

【每日一题 | 24.10.6】确定字符串是否包含唯一字符

1. 题目2. 解题思路3. 代码实现&#xff08;AC_Code&#xff09; 个人主页&#xff1a;C_GUIQU 归属专栏&#xff1a;每日一题 1. 题目 确定字符串是否包含唯一字符 2. 解题思路 题目要求&#xff1a;判断输入的字符串是否唯一&#xff0c;这里想到可以借助布尔数组。 第一…

软件测试外包干了4年,感觉废了....

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

【模板进阶】std::conditional

一、 s t d : : c o n d i t i o n a l std::conditional std::conditional的使用 C 11 C11 C11标准引入了 s t d : : c o n d i t i o n a l std::conditional std::conditional&#xff0c;这是一个类模板&#xff0c;用于表现一种编译期间的分支逻辑。 它的实现代码比较简…

【斯坦福CS144】Lab4

一、实验目的 完成一个网络接口实现。 二、实验内容 完成一个网络接口实现&#xff0c;其大部分工作是&#xff1a;为每个下一跳IP地址查找(和缓存)以太网地址。而这种协议被称为地址解析协议ARP。 三、实验过程 在minnow目录下输入git merge origin/check4-startercode获…

[ C++ ] C++ 类和对象 -- 类的六个默认成员函数

目录 1.构造函数 2.析构函数 3.拷贝构造函数 4.赋值操作符重载 5.两个取地址操作符的重载 在C中当你创建一个空类&#xff0c;那这个空类是什么都没有吗&#xff1f;不是的&#xff0c;编译器会默认帮你生成六个成员函数 1.构造函数 构造函数是特殊的成员函数&#xff0c;…

使用数据库:

数据库&#xff1a; 1.为何需要数据库&#xff1f; 存储数据方法 第一种&#xff1a;用大脑记住数据&#xff0c; 第二种&#xff1a;写纸上&#xff0c; 第三种&#xff1a;写在计算机的内存中&#xff0c; 第四种&#xff1a;写出磁盘文件 2.数据库能做什么&#xff1…

【探索艺术新纪元:Midjourney中文版,让创意无界!】

&#x1f3a8; 艺术&#xff0c;从此触手可及 在这个数字时代&#xff0c;Midjourney中文版正引领一场艺术创作的革命。作为一款前沿的AI绘画工具&#xff0c;它利用深度学习技术&#xff0c;将你的想象转化为触手可及的艺术作品。无需深厚的绘画功底&#xff0c;只需简单的文…

机器学习:opencv--图像拼接

目录 前言 一、两个函数 1.显示图像 2.计算图片特征与描述符 二、代码实例 1.准备图像 2.特征检测 3.特征匹配 4.图像变换 5.图像融合 前言 图像拼接是一种将多张图像合成一幅大图的技术&#xff0c;常用于全景图生成、图像拼接和图像合成等应用场景。 一、两个函数…

第二十三天|回溯算法| 39. 组合总和,40. 组合总和II,131. 分割回文串

目录 39. 组合总和 未剪枝 剪枝优化 40. 组合总和II 131. 分割回文串 回溯 回溯动态规划优化回文串判断 今天的题目自己都没啥思路&#xff0c;二刷的时候再理解一下。尤其是131. 39. 组合总和 本题和77.组合 &#xff0c;216.组合总和III的区别是&#xff1a;本题没有…

IDEA 输入英文字体变了的问题

**问题&#xff1a;**有时不知道按了什么快捷键导致在 IDEA 输入英文字体变了&#xff0c;如下所示&#xff0c;看起来特别不顺眼&#xff1a; 出现以上问题是因为在输入时切换了中文输入法&#xff0c;并且在提示文字时按了 Shift 空格 键&#xff0c;导致出现以上字体变化情…

H、Happy Number(2024牛客国庆集训派对day7)

题目链接&#xff1a; H-Happy Number_2024牛客国庆集训派对day7 (nowcoder.com) 题目描述&#xff1a; 翻译为中文&#xff1a; 数据范围&#xff1a; 输入样例&#xff1a; 680 输出样例&#xff1a; 326623 分析: 本来以为是dfs&#xff0c;但是看到数据范围1e9, 联想到是…

uniapp自定义导航,全端兼容

我们在用uniapp 开发应用的时候&#xff0c;有的页面需要自定义导航&#xff0c; 1.如果普通的直接使用uni 扩展柜组件的 uni-nav-bar 也基本够用&#xff0c; 2.如果稍微带点自定义的这个值无法支持的&#xff0c;特别在小程序端&#xff0c;胶囊是会压住右边的按钮的 自定…

多模态简单了解

多模态 1.文本编码2. ViT图像编码器2.1图像矩阵self-attention计算&#xff1a; 3.Transformer多模态3.1CLIP 图文交互3.2 对比学习训练3.3 flamingo 图文交互3.4 LLava 图文交互 1.文本编码 简介&#xff1a; 即通过embedding将字符向量化&#xff0c;进入模型即可。 2. ViT…

水下图像增强(论文复现)

本文所涉及所有资源均在 传知代码平台 可获取。 目录 概述 一、论文思路 二、模型介绍&#xff1a; 三、实现方法 四、复现过程(重要) 部署方式 概述 2021年11月&#xff0c;提出一种用于水下图像增强的U型Transformer模型&#xff0c;这是首次在水下图像增强任务中使用Transfo…