day31

今日内容概要

  • 组合

  • 反射(通过字符串来操作属性)

    • getattr

    • setattr

    • hasattr

    • delattr

  • 魔术方法(内置方法,双下滑线开头的方法)

  • 异常(剩余一部分)

  • 元类

组合

在一个类中以另外一个类的对象作为数据属性,称为类的组合

      组合与继承都是用来解决代码的重用性问题

不同的是:                                                                                                                                              继承是一种“是”的关系,比如老师是人、学生是人,当类之间有很多相同之处,应该使用继承;      而组合则是一种“有”的关系,比如老师有生日,老师有很多门课程,当类之间有显著不同,并且较小的类是较大的类所需要的组件时,应该使用组合

如下实例

 

class Course:def __init__(self,name,period,price):self.name=nameself.period=periodself.price=pricedef tell_info(self):print('<%s %s %s>' %(self.name,self.period,self.price))class Date:def __init__(self,year,mon,day):self.year=yearself.mon=monself.day=daydef tell_birth(self):print('<%s-%s-%s>' %(self.year,self.mon,self.day))class People:school='清华大学'def __init__(self,name,sex,age):self.name=nameself.sex=sexself.age=age#Teacher类基于继承来重用People的代码,基于组合来重用Date类和Course类的代码
class Teacher(People): #老师是人def __init__(self,name,sex,age,title,year,mon,day):super().__init__(name,age,sex)self.birth=Date(year,mon,day) #老师有生日self.courses=[] #老师有课程,可以在实例化后,往该列表中添加Course类的对象def teach(self):print('%s is teaching' %self.name)python=Course('python','3mons',3000.0)
linux=Course('linux','5mons',5000.0)
teacher1=Teacher('lili','female',28,'博士生导师',1990,3,23)# teacher1有两门课程
teacher1.courses.append(python)
teacher1.courses.append(linux)# 重用Date类的功能
teacher1.birth.tell_birth()# 重用Course类的功能
for obj in teacher1.courses: obj.tell_info()

此时对象teacher1集对象独有的属性、Teacher类中的内容、Course类中的内容于一身(都可以访问到),是一个高度整合的产物

反射

在python中,反射指的是通过字符串来操作对象的属性,涉及到四个内置函数的使用(python中一切皆对象都可以用下述四个方法)

class Teacher:def __init__(self,full_name):self.full_name =full_namet=Teacher('Egon Lin')# hasattr(object,'name')
hasattr(t,'full_name') # 按字符串'full_name'判断有无属性t.full_name# getattr(object, 'name', default=None)
getattr(t,'full_name',None) # 等同于t.full_name,不存在该属性则返回默认值None# setattr(x, 'y', v)
setattr(t,'age',18) # 等同于t.age=18# delattr(x, 'y')
delattr(t,'age') # 等同于del t.age

基于反射可以十分灵活地操作对象的属性,比如将用户交互的结果反射到具体的功能执行

>>> class FtpServer:
...     def serve_forever(self):
...         while True:
...             inp=input('input your cmd>>: ').strip()
...             cmd,file=inp.split()
...             if hasattr(self,cmd): # 根据用户输入的cmd,判断对象self有无对应的方法属性
...                 func=getattr(self,cmd) # 根据字符串cmd,获取对象self对应的方法属性
...                 func(file)
...     def get(self,file):
...         print('Downloading %s...' %file)
...     def put(self,file):
...         print('Uploading %s...' %file)
... 
>>> server=FtpServer()
>>> server.serve_forever()
input your cmd>>: get a.txt
Downloading a.txt...
input your cmd>>: put a.txt
Uploading a.txt...

内置方法

Python的Class机制内置了很多特殊的方法来帮助使用者高度定制自己的类,这些内置方法都是以双下划线开头和结尾的,会在满足某种条件时自动触发

我们以常用的__str__和__del__来介绍它们的使用

__str__,__repr__方法

__str__方法会在对象被打印时自动触发,print功能打印的就是它的返回值,我们通常基于方法来对象的打印信息,该方法必须返回字符串类型

>>> class People:
...     def __init__(self,name,age):
...         self.name=name
...         self.age=age
...     def __str__(self):
...         return '<Name:%s Age:%s>' %(self.name,self.age) #返回类型必须是字符串
... 
>>> p=People('lili',18)
>>> print(p) #触发p.__str__(),拿到返回值后进行打印
<Name:lili Age:18>class School:def __init__(self,name,addr,type):self.name=nameself.addr=addrself.type=typedef __repr__(self):return 'School(%s,%s)' %(self.name,self.addr)def __str__(self):return '(%s,%s)' %(self.name,self.addr)s1=School('oldboy1','北京','私立')
print('from repr: ',repr(s1))
print('from str: ',str(s1))
print(s1)

str函数或者print函数--->obj.__str__()

repr或者交互式解释器--->obj.__repr__()

如果__str__没有被定义,那么就会使用__repr__来代替输出

注意:这俩方法的返回值必须是字符串,否则抛出异常

__del__方法

__del__会在对象被删除时自动触发。

   由于Python自带的垃圾回收机制会自动清理Python程序的资源,所以当一个对象只占用应用程序级资源时,完全没必要为对象定制__del__方法,但在产生一个对象的同时涉及到申请系统资源(比如系统打开的文件、网络连接等)的情况下,关于系统资源的回收,Python的垃圾回收机制便派不上用场了,需要我们为对象定制该方法,用来在对象被删除时自动删除时自动触发回收系统资源的操作

class MySQL:def __init__(self,ip,port):self.conn=connect(ip,port) # 伪代码,发起网络连接,需要占用系统资源def __del__(self):self.conn.close() # 关闭网络连接,回收系统资源obj=MySQL('127.0.0.1',3306) # 在对象obj被删除时,自动触发obj.__del__()

isinstance(obj,cls)和issubclass(sub,super)

isinstance(obj,cls)检查是否obj是否是类cls的对象

class Foo(object):
2     pass
3  
4 obj = Foo()
5  
6 isinstance(obj, Foo)

issubclass(sub,super)检查sub类是否是super类的派生类

class Foo(object):passclass Bar(Foo):passissubclass(Bar, Foo)

__doc__

class Foo:'我是描述信息'passprint(Foo.__doc__)

class Foo:'我是描述信息'passclass Bar(Foo):pass
print(Bar.__doc__) #该属性无法继承给子类

__enter__和__exit__

# 我们知道在操作文件对象的时候可以这么写with open('a.txt') as f:'代码块'

上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法

class Open:def __init__(self,name):self.name=namedef __enter__(self):print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')# return selfdef __exit__(self, exc_type, exc_val, exc_tb):print('with中代码块执行完毕时执行我啊')with Open('a.txt') as f:print('=====>执行代码块')# print(f,f.name)

__exit__()中的三个参数分别代表:异常类型  异常值  追溯信息

with语句中代码块出现异常,则with后的代码都无法执行

class Open:def __init__(self,name):self.name=namedef __enter__(self):print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')def __exit__(self, exc_type, exc_val, exc_tb):print('with中代码块执行完毕时执行我啊')print(exc_type)print(exc_val)print(exc_tb)with Open('a.txt') as f:print('=====>执行代码块')raise AttributeError('***着火啦,救火啊***')
print('0'*100) #------------------------------->不会执行

如果__exit__()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行

class Open:def __init__(self,name):self.name=namedef __enter__(self):print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')def __exit__(self, exc_type, exc_val, exc_tb):print('with中代码块执行完毕时执行我啊')print(exc_type)print(exc_val)print(exc_tb)return Truewith Open('a.txt') as f:print('=====>执行代码块')raise AttributeError('***着火啦,救火啊***')
print('0'*100) #------------------------------->会执行

__setattr__,__delattr__,__getattr__

 

class Foo:x=1def __init__(self,y):self.y=ydef __getattr__(self, item):print('----> from getattr:你找的属性不存在')def __setattr__(self, key, value):print('----> from setattr')# self.key=value #这就无限递归了,你好好想想# 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

__setitem__,__getitem__,__delitem__

class Foo:def __init__(self,name):self.name=namedef __getitem__(self, item):print(self.__dict__[item])def __setitem__(self, key, value):self.__dict__[key]=valuedef __delitem__(self, key):print('del obj[key]时,我执行')self.__dict__.pop(key)def __delattr__(self, item):print('del obj.key时,我执行')self.__dict__.pop(item)f1=Foo('sb')
f1['age']=18
f1['age1']=19
del f1.age1
del f1['age']
f1['name']='alex'
print(f1.__dict__)

__call__

对象后面加括号,触发执行

构造方法的执行是由创建对象触发的 即:对象=类名;而对__call__方法的执行是由对象后加括号触发的 即:对象()或者类()()

class Foo:def __init__(self):passdef __call__(self, *args, **kwargs):print('__call__')obj = Foo() # 执行 __init__
obj()       # 执行 __call__

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

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

相关文章

【已解决】Python打包文件执行报错:ModuleNotFoundError: No module named ‘pymssql‘

【已解决】Python打包文件执行报错&#xff1a;ModuleNotFoundError: No module named pymssql 1、问题2、原因3、解决 1、问题 今天打包一个 tkinter pymssql 的项目的时候&#xff0c;打包过程很顺利&#xff0c;但是打开软件的时候&#xff0c;报错 ModuleNotFoundError: …

unity操作_刚体 c#

刚体Rigidbody 首先在场景中创建一个Plane 位置重置一下 再创建一个Cube 充值 y0.5 我们可以看出创建的Cube 和 Plane都自带碰撞器 Plane用的是网格碰撞器 我们可以通过网格世界看到不同的网格碰撞器 发生碰撞&#xff08;条件&#xff09;&#xff1a; 两个物体都有碰撞器 …

CentOS Integration SIG 正式成立

导读CentOS 董事会已批准成立 CentOS Integration Special Interest Group (SIG)。该小组旨在帮助那些在 Red Hat Enterprise Linux (RHEL) 或特别是其上游 CentOS Stream 上构建产品和服务的人员&#xff0c;验证其能否在未来版本中继续运行。 红帽 RHEL CI 工程师 Aleksandr…

IntelliJ IDEA 2023.1 版本可以安装了

Maven 的导入时间更加快了。 收到的有邮件提醒安装。 安装后的版本&#xff0c;其实就是升级下&#xff0c;并没有什么主要改变。 IntelliJ IDEA 2023.1 版本可以安装了 - 软件技术 - OSSEZMaven 的导入时间更加快了。 收到的有邮件提醒安装。 安装后的版本&#xff0c;其实就是…

基于goravel的CMS,企业官网通用golang后台管理系统

2023年9月11日10:47:00 仓库地址&#xff1a; https://gitee.com/open-php/zx-goravel-website 框架介绍 Goravel SCUI 后端开发组件 go 1.20 Goravel 1.13 数据库 sql(使用最新日期文件) goravel\doc\sql_bak mysql 8.0 前端开发组件 scui 1.6.9 node v14.21.3 效果图…

2023全网最全requests库和requests模块使用详解(建议收藏)

一、requests简介 #简介&#xff1a;使用requests可以模拟浏览器的请求&#xff0c;比起之前用的urllib&#xff0c;requests模块的api更加便捷&#xff08;本质就是封装了urllib3&#xff09;#注意&#xff1a;requests库发送请求将网页内容下载下来以后&#xff0c;并不会执…

点餐小程序实战教程08-购物车功能开发

目录 1 创建购物车2 增加数量3 减少数量4 切换分类时回填数据5 显示购物车信息总结 我们上一篇搭建了点餐业务的数据初始化加载&#xff0c;本篇实现一下加入购物车的功能。在购物车设计的时候有两种方案&#xff0c;一种是使用数据表的方案&#xff0c;一种是使用变量的方案。…

设计模式-享元模式

概念 共享内存&#xff08;主要考虑内存&#xff0c;而非效率&#xff09;相同的数据&#xff0c;共享使用&#xff08;JS中未找到经典应用场景&#xff09; 演示 <!-- 无限下拉列表&#xff0c;将事件代理到高层节点上 --> <!-- 如果都绑定到<a>标签&#x…

大型语言模型:RoBERTa — 一种鲁棒优化的 BERT 方法

一、介绍 BERT模型的出现导致了NLP的重大进展。BERT的架构源自Transformer&#xff0c;在各种下游任务上实现了最先进的结果&#xff1a;语言建模&#xff0c;下一句预测&#xff0c;问答&#xff0c;NER标记等。 大型语言模型&#xff1a;BERT — 来自变压器的双向编码器表示 …

如何在 Spring Boot 中提高应用程序的安全性

如何在 Spring Boot 中提高应用程序的安全性 Spring Boot是一种流行的Java开发框架&#xff0c;用于构建Web应用程序和微服务。在构建应用程序时&#xff0c;安全性是至关重要的因素。不论您的应用程序是面向公众用户还是企业内部使用&#xff0c;都需要采取适当的措施来确保数…

promtail multiline 堆栈日志处理

找到自己的promtail.yaml中job_name段落&#xff0c;增加multiline段落&#xff0c;下面文件只是部分内容&#xff0c;只需要修改firstline后面的正则表达式匹配日志行首&#xff0c;如果堆栈换行后不是此格式行首&#xff0c;将自动把堆栈的行合并到上一行中。 - job_name: k…

微信小程序 在bindscroll事件中监听scroll-view滚动到底

scroll-view其实提供了一个 bindscrolltolower 事件 这个事件的作用是直接监听scroll-view滚动到底部 但是 总有不太一样的情况 公司的项目 scroll-view 内部 最下面有一个 类名叫 bottombj 的元素 我希望 滚动到这个 bottombj 上面的时候就开始加载滚动分页 简单说 bottombj这…

c#设计模式-行为型模式 之 中介者模式

&#x1f680;简介 又叫调停模式&#xff0c;定义一个中介角色来封装一系列对象之间的交互&#xff0c;使原有对象之间的耦合松散&#xff0c;且可以独立地改变它们之间的交互。 从下右图中可以看到&#xff0c;任何一个类的变 动&#xff0c;只会影响的类本身&#xff0c;以及…

【Linux】基本指令-入门级文件操作(一)

目录 前言 ⭕linux的树状文件结构 ⭕绝对路径和相对路径 ⭕当前路径和上级路径 ⭕隐藏文件 基本指令&#xff08;重点&#xff09; 1 pwd 指令 2 mkdir 指令 3 touch 指令 4 ls 指令 4.1 ls只加选项不加文件/目录名&#xff0c;默认查看当前目录下的文件 4.1.1 ls -a…

【香橙派-OpenCV-Torch-dlib】TF损坏变成RAW格式解决方案及python环境配置

前言 本文将介绍在香橙派&#xff08;Orange Pi&#xff09;开发板上进行软件配置和环境搭建的详细步骤&#xff0c;以便运行Python应用程序。这涵盖了以下主要内容&#xff1a; 获取所需软件&#xff1a;提供了香橙派操作系统和balenaEtcher工具的下载链接&#xff0c;以确保…

flutter实现透明appbar(一)

前言 在项目中如何实现透明的appbar&#xff0c;方式一&#xff1a; 使用stack和positioned定位功能把appbar定位到页面的最上面&#xff0c; 实现 实现 Widget build(BuildContext context) {return Scaffold(body: Stack(children: [_homePage(), _appBar()],),);}_appbar…

图片大小转换(对于图片进行压缩)

传入的是图片途径 import java.io.*; import java.awt.image.BufferedImage; import javax.imageio.ImageIO; import java.util.Base64;// 限制图像大小为4MB public byte[] limitImageSize(File imageFile, int maxSizeInBytes) throws IOException {if (imageFile.length() …

BuyVM 拉斯维加斯 VPS 测评

description: 发布于 2023-07-05 BuyVM 拉斯维加斯 VPS 测评 产品链接&#xff1a;https://my.frantech.ca/cart.php?gid37 G口不限制流量&#xff0c;抗一般投诉&#xff0c;不抗版权投诉。 中国大陆连通性尚可。 CPU&#xff0c;硬盘速度不错。 规格 $3.50 USD/mo 1G…

js验证字符串是否是时间日期格式

参考文章 验证字符串是否是时间日期格式 返回 布尔值 表示 Dayjs的日期是否通过校验。 不严格的校验 只检查传入的值能否被解析成一个时间日期 dayjs(2022-01-33).isValid(); // true, parsed to 2022-02-02dayjs(some invalid string).isValid(); // false严格校验 检查…

vue中使用ali-oss上传文件到阿里云上

1.使用 npm 安装ali-oss npm install ali-oss --save2.写ali-oss.js // 引入ali-oss let OSS require(ali-oss) let client new OSS({region: oss-cn-xxx, // bucket所在的区域&#xff0c; 默认oss-cn-hangzhousecure: true, // secure: 配合region使用&#xff0c;如果指…