一 反射

# 静态语言:在执行前就定义好数据类型
# 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面向对象(反射、内置方法、元类)的更多相关文章

  1. python基础之反射内置方法元类

    补充内置函数 isinstance(obj,Foo)   # 判断obj是不是foo的实例 issubclass()      # 判断一个类是不是另一个类的子类 反射 什么是反射? 通过字符串来操作 ...

  2. Python—面向对象06 内置方法

    一 .isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object ...

  3. python面向对象反射-框架原理-动态导入-元类-自定义类-单例模式-项目的生命周期-05

    反射 reflect 反射(reflect)其实是反省,自省的意思 反省:指的是一个对象应该具备可以检测.修改.增加自身属性的能力 反射:通过字符串获取对象或者类的属性,进行操作 设计框架时需要通过反 ...

  4. python 面向对象的内置方法

    要求:了解即可,能用最好 """ 1.print(obj), str(obj), %s % (obj), 都调用obj.__str__()方法,若类中没有找__repr_ ...

  5. python常用数据类型内置方法介绍

    熟练掌握python常用数据类型内置方法是每个初学者必须具备的内功. 下面介绍了python常用的集中数据类型及其方法,点开源代码,其中对主要方法都进行了中文注释. 一.整型 a = 100 a.xx ...

  6. python字符串常用内置方法

    python字符串常用内置方法 定义: 字符串是一个有序的字符的集合,用与存储和表示基本的文本信息. python中引号中间包含的就是字符串. # s1='hello world' # s2=&quo ...

  7. python字符串处理内置方法一览表

    python字符串处理内置方法一览表   序号 方法及描述 1 capitalize()将字符串的第一个字符转换为大写 2 center(width, fillchar) 返回一个指定的宽度 widt ...

  8. python 面向对象进阶之内置方法

    一 isinstance(obj,cls)和issubclass(sub,super) 1.1,isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(obj ...

  9. 多态 鸭子类型 反射 内置方法(__str__,__del__) 异常处理

    ''' 1什么是多态 多态指的是同一种/类事物的不同形态 2 为何要有多态 多态性:在多态的背景下,可以在不用考虑对象具体类型的前提下而直接使用对象 多态性的精髓:统一 多态性的好处: 1增加了程序的 ...

  10. Python中class内置方法__init__与__new__作用与区别探究

    背景 最近尝试了解Django中ORM实现的原理,发现其用到了metaclass(元类)这一技术,进一步又涉及到Python class中有两个特殊内置方法__init__与__new__,决定先尝试 ...

随机推荐

  1. Excel 分列功能 帮助 用户 导入Excel

    今天遇见一个客户的 Excel有一列 就是 导入不进去  那列 基本都是 数字 我试了下  写入几个字符 就能导入  不写字符的 就是导入 不进去 龚蓼 告诉我 用分列功能 今天试了下  草 果然可以 ...

  2. Oracle-报错信息显示问号或者乱码(Oracle 19c)

    问题描述: 通过sqlplus登录Oracle19c时,执行SQL出现报错时,显示错误码出现问号: 解决方法: su   -  oracle vi .bash_profile 添加如下一行内容: ex ...

  3. 使用explain分析Spark SQL中的谓词下推,列裁剪,映射下推

    一.谓词下推 Predicate PushDown 谓词下推的目的:将过滤条件尽可能地下沉到数据源端. 谓词,用来描述或判定客体性质.特征或者客体之间关系的词项,英文翻译为predicate,而谓词下 ...

  4. NC201613 Jelly

    题目链接 题目 题目描述 Nancy喜欢吃果冻! Nancy钻进了一个 \(n \times n \times n\) 的果冻里,她想从(1,1,1)一路上.下.左.右.前.后六个方向吃到(n,n,n ...

  5. Slot 的含义

    Slot 解释 1)slot就是槽的意思,是一个资源单位,只有给task分配了一个slot之后,这个task才可以运行.slot分两种,map slot沪蓉reduce slot.另外,slot是一个 ...

  6. 【Unity3D】UGUI之Slider

    1 Slider属性面板 ​ 在 Hierarchy 窗口右键,选择 UI 列表里的 Slider 控件,即可创建 Slider 控件,选中创建的 Slider 控件,按键盘[T]键,可以调整 Sli ...

  7. Swoole从入门到入土(23)——多进程[进程池Process\Pool]

    Swoole提供的进程池为Process\Pool,基于 Swoole\Server 的 Manager 管理进程模块实现.可管理多个工作进程.该模块的核心功能为进程管理,相比 Process 实现多 ...

  8. [技术选型与调研] 流程引擎(工作流引擎|BPM引擎):Activiti、Flowable、Camunda

    1 概述:流程与流程引擎 低代码平台.办公自动化(OA).BPM平台.工作流系统均需要[流程引擎]功能 BPM平台与工作流系统的区别,参见本文档:3.2 章节 流程引擎是任务分配软件(例如业务流程管理 ...

  9. centos7安装postgresql9.6

    1.安装yum源 yum install -y https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-7-x86_64/pgdg- ...

  10. C++ { } 的使用场景

    {} 可以用于初始化 C++11 中的变量,就像它们用于初始化 C 中的数组和结构一样. {} 主要是为了提供语法的一致性(使用 {} 初始化将在所有上下文中都有效,而使用赋值运算符或()初始化将在特 ...