python全栈学习记录(二十三)反射、内置方法、类相关的函数、元类

反射、内置方法、类相关的函数、元类

文章目录

  • 反射、内置方法、类相关的函数、元类
  • 一、反射
  • 二、内置方法
    • 1.__str__
    • 2.__repr__
    • 3.__del__
    • 4.__getattr__
    • 5.__setattr__
  • 三、类相关的函数
  • 四、元类
    • 1.python中类的产生过程
    • 2.元类控制类的产生

一、反射

反射的意思是通过字符串来操作类或者对象的属性,而在常规的方法中我们是通过x.y这种变量名的形式操作类或者对象的属性的。
反射涉及到四个内置函数:

  • hasattr(obj,name)用于查看对象是否具有某属性,是则返回True,否则返回False
  • getattr(obj,name,default)用于获取对象的某个属性,若对象没有该属性则返回default,不指定default则会报错
  • setattr(obj,name,value)用于给对象的某个属性赋值
  • delattr(obj,name)用于从对象中删除某个属性
class People:country='China'count=14*10e8
p=People()print(hasattr(p,'country'))
print(hasattr(p,'name'))<<<True
<<<Falseprint(getattr(p,'count','您查询的值不存在'))
print(getattr(p,'name','您查询的值不存在'))<<<14000000000.0
<<<您查询的值不存在print(hasattr(p,'position'))
setattr(p,'position','Asia')
print(getattr(p,'position'))<<<False
<<<Asiaprint(hasattr(People,'count'))
delattr(People,'count')
print(hasattr(People,'count'))<<<True
<<<False

反射的一大用处是可以动态的调用对象的值(当调用的对象值不存在时也不会报错)

def run():print('from run')def jump():print('from jump')def run_function(obj,function):if hasattr(obj,function):getattr(obj,function)()else:print('函数%s不存在'%function)import sys
#获取当前运行模块的内存地址
this_module=sys.modules[__name__]run_function(this_module,'jump')
run_function(this_module,'run')
run_function(this_module,'swim')<<<from jump
<<<from run
<<<函数swim不存在

二、内置方法

python的类内置了许多以__开头,以__结尾的方法,这些方法是在满足特定条件时自动触发的,如__init__的作用是初始化类的实例,会在类的实例创建完成以后自动触发 。

1.str

__str__方法会在类的对象被打印时自动触发,用于定制对象的打印值,返回值必须是字符串

class A():def __str__(self):return '111'print(A())
<<<111

2.repr

在交互式界面输出类的的对象时会触发__repr__方法
在这里插入图片描述

3.del

__del__方法会在对象被删除时触发。由于python有垃圾回收机制,会自动回收资源,使用当对象只是占用程序级资源时完全没有必要定制__del__方法。但是当对象涉及到向操作系统申请资源时就可以通过定制__del__方法来自动回收占用系统的资源了。

#假设文件中存着用户信息
class ReadUser():def __init__(self):self.f=open('user.txt','r',encoding='utf-8')self.user=self.f.read()def __del__(self):#当垃圾回收机制回收ReadUser时自动关闭操作系统中打开的文件self.f.close()

4.getattr

当访问对象的某属性不存在时会调用__getattr__(self,name)方法并将属性名传给name,返回__getattr__的返回值,如果没有返回值则报错

class A():num=1def __getattr__(self, name):return '%s属性不存在'%namea=A()
print(a.num)
print(a.t)<<<1
<<<t属性不存在

5.setattr

当对对象的属性赋值时会触发__setattr__(self,name,val)方法,name为属性名,val为给属性赋的值。

class A():def __setattr__(self, name,val):if name=='name' and type(val) is str:#完成正常的赋值操作super().__setattr__(name,val)else:print('名字必须为字符串')a=A()
a.name=99
a.name='张三'
print(a.name)<<<名字必须为字符串
<<<张三

三、类相关的函数

isinstance(obj,f)表示判断obj是否是f类的实例(如果obj是f的实例,f1是f的父类,isinstance(obj,f1)也返回True)
insubclass(obj,f)表示判断obj是否为f的子类
type(obj)表示判断obj所属的类

class B():pass
class A(B):passa=A()
print(isinstance(a,A))
print(isinstance(a,B))
print(issubclass(A,B))
print(type(a))
print(type(int))<<<True
<<<True
<<<True
<<<< class '__main__.A'>
<<< <class 'type'>

四、元类

在python中一切皆对象,那么我们用class关键字定义的类本身也是一个对象,而负责产生该对象的类称之为元类,即元类可以简称为类的类。

元类的目的:控制类的产生过程

1.python中类的产生过程

python中类的产生的三要素:类名(class_name)、基类(class_bases)(父类)、名称空间(class_dic)。
我们可以使用exec和type函数手动产生一个类(exec(f,globals,locals)函数用于执行字符串形式的命令f并将产生的变量以字典形式存放于全局/局部,也就是globals/locals中)

class_name='People'
class_bases=(object,)
class_dic={}
class_body="""
country='China'
def __init__(self,name,age):self.name=nameself.age=age
def eat(self):print('%s is eating' %self.name)
"""
#执行class_body中代码并将产生的局部变量存放于class_dic
#相当于产生了类的名称空间
exec(class_body,{},class_dic)
#产生类,People变量中存放的是类People的内存地址
People=type(class_name,class_bases,class_dic)print(People)
p=People('张三',18)
print(p.country,p.name,p.age)<<<<class '__main__.People'>
<<<China 张三 18

由上面类产生的过程我们可以知道class关键字创建类的流程就是:拿到类名、确定基类(父类)、产生名称空间、用type产生类。

2.元类控制类的产生

当一个类继承了type类,那么它就是一个元类,用来控制指定类的产生过程。
__new__方法是一个绑定给类的内置方法,负责产生一个新的对象,会在实例产生时调用。

class A():def __new__(cls):print(111)return super().__new__(cls)a=A()
<<<111

元类中的__new__方法负责完成类产生的整个过程(拿到类名、确定基类(父类)、产生名称空间、用type产生类),并且这个过程是在类的定义阶段完成的,话句话说就是元类是在类的定义阶段被调用的。

class Mymeta(type):def __new__(cls,class_name,class_bases,class_dic):#绑定给类的方法中调用super()时,第一个参数必须传入clsprint(cls)class_dic.update({'a': 111, 'b': 222})return super().__new__(cls,class_name,class_bases,class_dic)class A(metaclass=Mymeta):passprint(A.__dict__)
<<< <class '__main__.Mymeta'>
<<<{'__module__': '__main__', 'a': 111, 'b': 222, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}

上述代码中可以看到,解释器运行到class A(metaclass=Mymeta):时会调用元类Mymeta,并触发__new__方法,将类名、基类和名称空间字典传入元类的__new__方法中产生类。可以看到当在元类中传入的名称空间中添加两个值以后,也可以在类A的__dict__中看到这两个值。

类产生过程中h

基于上述过程我们就可以在类产生的过程中加上一些限制以达到自定义类的效果,例如让类必须带上注释文档(带注释文档的类__dict__中__doc__属性中会存放注释文档内容)

class Mymeta(type):def __new__(cls,class_name,class_bases,class_dic):if '__doc__' not in class_dic:raise ValueError("类必须带上注释文档")return super().__new__(cls,class_name,class_bases,class_dic)class A(metaclass=Mymeta):pass<<<ValueError: 类必须带上注释文档
class Mymeta(type):def __new__(cls,class_name,class_bases,class_dic):if '__doc__' not in class_dic:raise ValueError("类必须带上注释文档")else:print(class_dic['__doc__'])return super().__new__(cls,class_name,class_bases,class_dic)class A(metaclass=Mymeta):'''111'''<<<111

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

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

相关文章

大模型应用探讨,免费AI写作、一键PPT、免费PDF百种应用、与AI对话

大模型应用平台知识普及, 应用可见评论区 我们生活在一个充满无限可能的数字时代&#xff0c;人工智能技术正在推动着各种创新的边界。大模型应用平台一般包含以下功能。 ## 1. 一键生成论文 写作是学生、研究人员和职场人士都无法避免的任务。大模型应用平台拥有强大的文本生…

Lesson3 - 操作系统软件视角和系统调用

文章目录 硬件支持系统 系统管理硬件异步行为中断的分类 同步行为虚拟地址空间shell系统调用与软中断区分系统调用trace 命令 硬件支持系统 系统管理硬件 计算机硬件由三样东西组成&#xff1a;CPU、内存、I/O设备。为了更有效地管理这些硬件资源&#xff0c;系统设计者引入了…

使用bert模型进行命名实体识别任务

一、实验内容 本实验使用预训练的 BERT 模型进行命名实体识别&#xff08;NER&#xff09;任务&#xff0c;并且使用 Hugging Face 的 Transformers 库完成模型的训练、验证和测试。最后&#xff0c;使用测试集评估模型性能&#xff0c;计算NER指标。 二、算法介绍 Bert是一种…

Observability:使用 OpenTelemetry 自动检测 Go 应用程序

作者&#xff1a;来自 Elastic Damien Mathieu 使用 OpenTelemetry 检测 Go 应用程序可以深入了解应用程序的性能、依赖项和错误。我们将向你展示如何使用 Docker 自动检测 Go 应用程序&#xff0c;而无需更改应用程序代码。 在快节奏的软件开发领域&#xff0c;尤其是在云原生…

分治算法(3)_快速选择_数组中的第K个最大元素

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 分治算法(3)_快速排序_数组中的第K个最大元素 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#…

【原创】Anaconda+VScode+PySide6 完美配置Python开发环境,亲测!

准备工作 下载安装 Anaconda 下载安装Visual Studio Code 配置系统环境变量 配置Anaconda环境变量 将Anaconda安装目录及Scripts 、Library\bin 两个子目录添加到用户变量或系统变量的Path变量中。 Anaconda自带最新版Python&#xff0c;如果已经安装Python&#xff0c;建议…

Mybatis测试案例

1.创建springboot工程 创建实体类user和接口 user类 注意&#xff1a;java和mysql的对象的属性数据类型要一致 mapper接口 2.配置mybatis(连接数据库信息) # spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver #地址url spring.datasource.urljdbc:mysql://localho…

【Python】Mistune:高效的 Python Markdown 解析器

Mistune 是一个轻量且强大的 Python Markdown 解析器。它的设计目标是兼顾速度和扩展性&#xff0c;同时兼容 CommonMark 标准。Mistune 支持多种渲染器&#xff08;Renderers&#xff09;和插件&#xff0c;能够根据需求将 Markdown 转换为 HTML、LaTeX 或自定义格式。此外&am…

Java中数组的应用

Java中数组的应用 数组数组的使用使用方式1-动态初始化数组的定义&#xff1a;数组的引用&#xff08;使用/访问/获取数组元素&#xff09;&#xff1a;快速入门案例 使用方式2-动态初始化**先声明**数组**再创建**数组使用方式1和2的比较 使用方式3-静态初始化初始化数组快速入…

[嵌入式Linux]—STM32MP1启动流程

STM32MP1启动流程 1.启动模式 STM32MP1等SOC支持从多种设备中启动&#xff0c;如EMMC、SD、NAND、NOR、USB、UART等。其中USB、UART是作为烧录进行启动的。 STM32MP1内部ROM中存储有一段出厂代码来进行判断从哪种设备中启动&#xff0c;上电后这段代码会被执行&#xff0c;这…

CPU中的寄存器是什么以及它的工作原理是什么?

在计算机科学中&#xff0c;寄存器是数字设备中的一个重要组成部分&#xff0c;它用于存储数据和指令以快速处理。寄存器充当临时存储区&#xff0c;信息可以在这里被快速访问和操作&#xff0c;以执行复杂任务。寄存器是计算机中最基础的存储类型&#xff0c;它们在帮助机器高…

【Unity】版本不一致且未升级资产,导致 Unity Sprite 2D 动画播放错误

自己的 Unity版本是 2022.3.45f1。目前折腾的这插件 2D Action RPG Engine: Mythril2D &#xff0c;推荐使用的 Unity 版本是 2021.3.18。 倒腾了这个 unity animation 动画半天&#xff0c;发现这个 animation sprite resolver 在导入动画帧的时候&#xff0c;一直都导入的是…

allegro 替换过孔

操作步骤如下 1.选择操作对象&#xff08;需要替换的过孔&#xff09;&#xff0c;右键–>Repace……–>Selected…… 2.在弹出的窗口中选择最终需要的过孔既可以

【Matlab学习日记】② 常用滤波以及噪声分析方法(上)

关注星标公众号&#xff0c;不错过精彩内容 作者 | 量子君 微信公众号 | 极客工作室 【Matlab学习日记】专栏目录 第一章 ① Sinmulink自动代码生成教程 第二章 ② 常用滤波以及噪声分析方法&#xff08;上&#xff09; 文章目录 前言一、使用滤波的目的二、常见的几种噪声和表…

算法闭关修炼百题计划(四)

仅供个人复习 1.两数相加2.寻找峰值3.寻找旋转排序数组中的最小值4.寻找旋转排序数组中的最小值II5.搜索旋转排序数组6.岛屿的最大面积7.最大数8.会议室9.最长连续序列 1.两数相加 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储…

STM32 通用同步/异步通信

一、串行通信简介 CPU与外围设备之间的信息交换称为通信。基本的通信方式有并行通信和串行通信两种。STM32单片机提供了功能强大的串行通信模块&#xff0c;即通用同步/异步收发器&#xff08;USART&#xff09;。 1.串行通信 串行通信是数据字节一位一位地依次传送的通信方式。…

毕业设计 深度学习水果识别

文章目录 1 前言2 开发简介3 识别原理3.1 传统图像识别原理3.2 深度学习水果识别 4 数据集5 部分关键代码5.1 处理训练集的数据结构5.2 模型网络结构5.3 训练模型 6 识别效果 1 前言 Hi&#xff0c;大家好&#xff0c;这里是丹成学长&#xff0c;今天做一个 基于深度学习的水果…

毕业设计——医院信息化系统原型设计

作品详情 主要功能&#xff1a; 信息化系统是以患者为中心&#xff0c;服务于重症科室医务人员&#xff0c;提高工作效率及医疗服务质量。软件主要包含了重症医学临床管理系统和中央监控站&#xff0c;重症医学临床管理系统主要实现患者床位总览、患者护理、医嘱管理、数据字典…

JS 介绍/书写位置/输入输出语法

目录 1. JS 介绍 1.1 JS 是什么 1.2 JS 的作用 1.3 JS 的组成 2. JS 书写位置 2.1 内部 JS 2.2 外部 JS 2.3 内联 JS 3. JS 注释和结束符 4. JS 输入输出语法 4.1 输入语法 4.2 输入语句 4.3 执行顺序 5. 字面量 1. JS 介绍 1.1 JS 是什么 1.2 JS 的作用 1.3 JS …