python面向对象(反射、内置方法、元类)
一 反射
# 静态语言:在执行前就定义好数据类型
# var x int=8
# 动态语言:在执行的时候,才识别数据类型
# x = 8
# 什么是反射?
# 指的是在程序运行过程中可以“动态”获取对象的信息 # 为何要用反射?
# 函数调用对象时,不知道对象下面,有哪些属性,所以要用到反射 # 如何实现反射?----》用字符串来操作对象的属性和方法
class People:
def __init__(self, name, age):
self.name = name
self.age = age def say(self):
print('我的名字:{},年龄是{}!'.format(self.name, self.age)) obj = People('lq', 19) # 1.先通过dir查看某一个对象下可以.出哪些属性来
print(dir(obj)) # 对象含有的属性列表 # 2、可以通过字符串反射到真正的属性上,得到属性值
print(obj.__dict__['name'])
# lq
print(obj.__dict__[dir(obj)[-2]])
# lq # 四个内置函数的使用:通过字符串来操作属性值
# 1、hasattr()
print(hasattr(obj, 'name')) # True或False,看该对象下有没有该属性 # 2、getattr()
print(getattr(obj, 'name')) # 获取属性值
# lq
# 3、setattr()
setattr(obj, 'name', 'xiaobao') # 更改属性值
print(obj.name)
# xiaobao # 4、delattr()
delattr(obj, 'name')
print(obj.__dict__) # 不在含有就'name'属性
# 方法的调用 res1 = getattr(obj, 'say')
res2 = getattr(People, 'say')
print(res1) # obj.say()
print(res2) # People.say()
# 例(反射)
class Ftp:
def put(self):
print('正在执行上传功能') def get(self):
print('正在执行下载功能') def interactive(self):
choice = input('请输入:') # 字符串,'put' if hasattr(self, choice):
getattr(self, choice)() # choice是字符串
else:
print('输入的指令不存在') obj = Ftp()
obj.interactive()
'''
请输入:get
正在执行下载功能
'''
二 内置方法
# 1、什么是内置方法?
# 定义在类内部,以__开头并以__结果的方法
# 特点:会在某种情况下自动触发执行,作用和类下面的__init__作用一样 # 2、为何要用内置方法?
# 为了定制化我们的类or对象 # 3、如何使用内置方法
# __str__:在打印对象时会自动触发,然后将返回值(必须是字符串类型)当做本次打印的结果输出
class People:
def __init__(self, name, age):
self.name = name
self.age = age def __str__(self):
print('hahah')
return '我叫{},今年{}'.format(self.name, self.age) obj = People('lq', 19)
print(obj) # 可以直接打印对象,不在显示内存地址
'''
hahah
我叫lq,今年19
''' # __del__:在清理对象时触发,会先执行该方法
class People:
def __init__(self, name, age):
self.name = name
self.age = age
self.x = open('a.txt', mode='w') def __del__(self):
print('hahah')
# 发起系统调用,告诉操作系统回收相关的系统资源
self.x.close() obj = People('lq', 19)
print('----->')
'''
-----> 程序运行完了,回收内存后,再触发__del__方法
hahah
'''
三 元类
1、什么是元类
一切皆为对象
什么是元类?
元类就是用来实例化产生类的类
关系:元类---》实例化--》类(People)-->实例化--》对象(obj)
class People:
def __init__(self, name, age):
self.name = name
self.age = age def say(self):
print('我叫{},今年{}'.format(self.name, self.age)) # 如何得到对象
# obj=调用类()
obj = People('xiaobao', 6)
print(type(obj)) # <class '__main__.People'> # 如何说类也是对象
# People=调用类() # 查看内置的元类:
# 1、type是内置的元类
# 2、我们用class关键字定义的所有的类以及内置的类都是由内置的元类type帮我们实例化产生
print(type(People))
# <class 'type'>
print(type(int))
# <class 'type'>
2、class关键字创造类People的步骤
# 类有三大特征:
# 1、类名
class_name = 'People'
# 2、类的基类
class_bases = (object,)
# 3、执行类体代码拿到类的名称空间
class_dict = {}
class_body = '''
def __init__(self, name, age):
self.name = name
self.age = age def say(self):
print('我叫{},今年{}'.format(self.name, self.age))
'''
exec(class_body, {}, class_dict) print(class_dict)
# {'__init__': <function __init__ at 0x0000011D742A9280>, 'say': <function say at 0x0000011D743A24C0>} # 4、调用元类
People = type(class_name, class_bases, class_dict)
print(People)
# <class '__main__.People'>
3、如何自定义元类来控制类的产生
class Mymeta(type): # 只有继承了type类的类才是元类
def __init__(self, x, y, z):
print('run---')
print(self)
print(x)
print(y)
print(z) # 当前所在的类,调用类时所传入的参数
def __new__(cls, *args, **kwargs):
# 造Mymeta的对象
print('run2222')
print(cls, args, kwargs)
# <class '__main__.Mymeta'>
# ('People', (), {'__module__': '__main__', '__qualname__': 'People',
# '__init__': <function People.__init__ at 0x0000010D59172040>,
# 'say': <function People.say at 0x0000010D59172670>})
# {}
# return super().__new__(cls,*args,**kwargs) # 继承父类
return type.__new__(cls, *args, **kwargs) # 第一步产生空对象的来源 # People=Mymeta(class_name,class_bases,class_dic)
# 调用Mymeta发生三件事
# 1、先造一个空对象--》People,调用类内的__new__方法
# 2、调用Mymeta这个类内的__init__方法,完成初始化对象的操作
# 3、返回初始化好的对象
class People(metaclass=Mymeta):
def __init__(self, name, age):
self.name = name
self.age = age def say(self):
print('我叫{},今年{}'.format(self.name, self.age)) # 强调:
# 只要是调用类,那么会一次调用
# 1)、类内的__new__
# 2)、类内的__init__
4、__call__
class Foo:
def __init__(self, x, y):
self.x = x
self.y = y def __call__(self, *args, **kwargs):
print('---->', args, kwargs)
return 123 obj = Foo(1, 2)
res = obj(1, 2, 3, a=4, b=5, c=6) # 对象可被调用
print(res) # 应用:如果想让一个对象可以加括号调用,需要在该对象的类中添加一个方法__call__
# 总结:
# 对象()---》类内的__call__
# 类()---》自定义元类内的__call__
# 自定义元类()---》内置元类__call__
5、自定义元类控制类的调用---》类的对象的产生
class Mymeta(type): # 只有继承了type类的类才是元类
def __call__(self, *args, **kwargs):
# 1、Mymeta.__call__函数内会先调用People内的 __new__
people_obj = self.__new__(self)
# 2、Mymeta.__call__函数内会调用People内的__init__
self.__init__(people_obj, *args, **kwargs)
# 3、Mymeta.__call__函数内会返回一个初始化好的对象
return people_obj # 类的产生
# People=Mymeta()--> type.__call__--->干了三件事
# 1、type.__call__函数内会先调用Mymeta内的__new__
# 2、type.__call__函数内会调用Mymeta内的__init__
# 3、type.__call__函数内会返回一个初始化好的对象 class People(metaclass=Mymeta):
def __init__(self, name, age):
self.name = name
self.age = age def say(self):
print('我叫{},今年{}'.format(self.name, self.age)) def __new__(cls, *args, **kwargs):
# 产生真正的对象
return object.__new__(cls)
6、属性查找

# 属性查找的原则:对象---》类---》父类
# 切记:父类 不是 元类
# 1--》2--》3--》4--》5--》6
四 元类总结
类是元类的实例化:
1、造空对象,就是元类来造空对象,元类调用自己__new__
2、初始化空对象,就是元类调用自己的__init__方法
__new__和__init__方法都是在__call__方法下,__new__在__init__
3、返回初始化好的对象,就方法__call__的返回值
五 更多反射和魔法方法,看下文
https://www.cnblogs.com/liuqingzheng/articles/9949568.html
https://www.cnblogs.com/liuqingzheng/articles/9949568.html
python面向对象(反射、内置方法、元类)的更多相关文章
- python基础之反射内置方法元类
补充内置函数 isinstance(obj,Foo) # 判断obj是不是foo的实例 issubclass() # 判断一个类是不是另一个类的子类 反射 什么是反射? 通过字符串来操作 ...
- Python—面向对象06 内置方法
一 .isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object ...
- python面向对象反射-框架原理-动态导入-元类-自定义类-单例模式-项目的生命周期-05
反射 reflect 反射(reflect)其实是反省,自省的意思 反省:指的是一个对象应该具备可以检测.修改.增加自身属性的能力 反射:通过字符串获取对象或者类的属性,进行操作 设计框架时需要通过反 ...
- python 面向对象的内置方法
要求:了解即可,能用最好 """ 1.print(obj), str(obj), %s % (obj), 都调用obj.__str__()方法,若类中没有找__repr_ ...
- python常用数据类型内置方法介绍
熟练掌握python常用数据类型内置方法是每个初学者必须具备的内功. 下面介绍了python常用的集中数据类型及其方法,点开源代码,其中对主要方法都进行了中文注释. 一.整型 a = 100 a.xx ...
- python字符串常用内置方法
python字符串常用内置方法 定义: 字符串是一个有序的字符的集合,用与存储和表示基本的文本信息. python中引号中间包含的就是字符串. # s1='hello world' # s2=&quo ...
- python字符串处理内置方法一览表
python字符串处理内置方法一览表 序号 方法及描述 1 capitalize()将字符串的第一个字符转换为大写 2 center(width, fillchar) 返回一个指定的宽度 widt ...
- python 面向对象进阶之内置方法
一 isinstance(obj,cls)和issubclass(sub,super) 1.1,isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(obj ...
- 多态 鸭子类型 反射 内置方法(__str__,__del__) 异常处理
''' 1什么是多态 多态指的是同一种/类事物的不同形态 2 为何要有多态 多态性:在多态的背景下,可以在不用考虑对象具体类型的前提下而直接使用对象 多态性的精髓:统一 多态性的好处: 1增加了程序的 ...
- Python中class内置方法__init__与__new__作用与区别探究
背景 最近尝试了解Django中ORM实现的原理,发现其用到了metaclass(元类)这一技术,进一步又涉及到Python class中有两个特殊内置方法__init__与__new__,决定先尝试 ...
随机推荐
- JS leetcode 猜数字 题解分析,我以为题目在第八层我在第一层,其实我在第三层题目在第一层
壹 ❀ 引 今天来做一道简单到让我一度怀疑题目本意的题目,题目来自leetcode LCP 01. 猜数字,题目描述如下: 小A 和 小B 在玩猜数字.小B 每次从 1, 2, 3 中随机选择一个,小 ...
- Java核心技术卷1:基础知识(原书第10版)
本书为专业程序员解决实际问题而写,Java基础知识面覆盖很完整,可以帮助你深入了解Java语言和库.在卷I中,Horstmann主要强调基本语言概念和现代用户界面编程基础,深入介绍了从Java面向对象 ...
- 【Unity3D】UGUI回调函数
1 简述 UGUI 回调函数主要指鼠标进入.离开.点下.点击中.抬起.开始拖拽.拖拽中.拖拽结束 UI 控件触发的回调.使用 UGUI 回调函数时,需要引入 UnityEngine.EventSy ...
- Js中RegExp对象
Js中RegExp对象 RegExp对象表示正则表达式,是由普通字符和特殊字符也叫元字符或限定符组成的文字模板,用于对字符串执行模式匹配. 描述 创建一个RegExp对象通常有两种方式,一种是通过字面 ...
- 高效发现和解决insert字段长度不够的报错
早上发现执行的PostgreSQL 存储过程报错,错误如下: 300-value too long for type character varying(100),一看就是表字段的长度太小,从提示看是 ...
- Java I/O 教程(十 一) BufferedWriter和BufferedReader
Java BufferedWriter 类 Java BufferedWriter class 继承了Writer类,为Writer实例提供缓冲. 提升了写字符和字符串性能. 类定义: public ...
- Programming Abstractions in C阅读笔记:p293-p302
<Programming Abstractions in C>学习第73天,p293-p302总结,总计10页. 一.技术总结 1.时间复杂度 (1)quadratic time(二次时间 ...
- android:加载PDF几种方法汇总对比
在安卓项目中,加载PDF文件,是一个比较常见的需求.又分为两大类, 1.加载网络PDF 2.加载一个本地静态PDF. 查阅资料,纵观网上在安卓中打开PDF的各种方式,大致可以分为以下几类, 1.直接使 ...
- 基于kubeadm部署k8s1.80.0
k8s搭建 硬件要求 测试环境 # master 2核 4G 20G # node 4核 8G 40G 生产环境 # master 8核 16G 100G # node 16核 64G 500G 方式 ...
- 《Similarity-based Memory Enhanced Joint Entity and Relation Extraction》论文阅读笔记
代码 原文 摘要 文档级联合实体和关系抽取是一项难度很大的信息抽取任务,它要求用一个神经网络同时完成四个子任务,分别是:提及检测.共指消解.实体分类和关系抽取.目前的方法大多采用顺序的多任务学习方式, ...