什么是反射:
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
Python面向对象的反射:
通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
#### 四个实现反射的函数
# hasattr(), getattr(), setattr(), delattr()
#### 反射 整合版
class Foo:
public_attr='静态属性'
def __init__(self,name,age):
self.name=name
self.age=age
def func(self):
print('Hello Python')
obj=Foo('张三',18) # 实例化对象
## 检测是否含有XX属性
print(hasattr(obj,'public_attr')) #当前实例对象,是否含有静态变量public_attr
print(hasattr(obj,'func')) #当前实例对象,是否含有func方法
## 获取属性 getattr(对象,字符串,None)
print(getattr(obj,'public_attr'),None) #静态属性,不存在就返回None
print(getattr(obj,'func')) # <bound method Foo.func of <__main__.Foo object at 0x0000015FF30EC8D0>>
## 设置属性 setattr(对象,字符串,值)
setattr(obj,'sex','男') # 设置对象属性
print(obj.__dict__) # {'name': '张三', 'age': 18, 'sex': '男'}
## 设置匿名方法 self为参数
setattr(obj,'show_name',lambda self:self.name)
print(obj.show_name(obj)) # 设置方法,
print(obj.__dict__)# { 'show_name': <function <lambda> at 0x0000018512932EA0>}
## 删除属性
delattr(obj,'name')
delattr(obj,'name') # 不存在就报错
print(obj.__dict__) # {'age': 18, 'sex': '男', 'show_name': <function <lambda> at 0x000001D901BE2EA0>}
### 从当前 脚本(本类) 研究反射
class B:
sta_='abc'
def func1():
print('in func1')
import sys
this_module=sys.modules[__name__] # 获取py文件对象
print(this_module) # 这是一个对象 <module '__main__' from 'E:/File/oldboy学习笔记/Python之路/day26/01 反射.py'>
print(hasattr(this_module,'func1')) # 判断函数名属性 存在不存在, True
print(getattr(this_module,'func1')) # 获得函数名属性 <function func1 at 0x00000225EBA92EA0>
getattr(this_module,'func1')() #获得函数名属性+()执行func1函数
print(hasattr(this_module,'B')) # 判断类名属性 存在不存在 True
print(getattr(this_module,'B')) # 获得类名属性打印 <class '__main__.B'>
cls=getattr(this_module,'B') # cls 得到是一个B类的地址
print(cls) # <class '__main__.B'>
obj=cls() # cls+() 实例化一个对象
print(obj.sta_) # obj对象.B对象中的静态属性
案例:
class Auth:
funcli=[('login','请登录'),('register','请注册'),('exit','退出')]
def login(self):
print('登录函数')
def register(self):
print('注册函数')
def exit(self):
print('退出...')
while 1:
obj=Auth()
for num , option in enumerate(obj.funcli,1):
print(num,option[0],option[1])
func_name = input('请输入选择:').strip()
if hasattr(obj,obj.funcli[int(func_name)-1][0]):
getattr(obj,obj.funcli[int(func_name)-1][0],'不存在')()
二丶函数vs方法
函数和方法有什么区别和相同之处?
函数是显性传参, 方法是隐性传参
#### 通过打印函数名确定
def func():
pass
print(func) # 函数 <function func at 0x00000260A2E690D0>
class A:
def func(self):
pass
print(A.func) # 函数 <function A.func at 0x0000026E65AE9C80>
obj = A()
print(obj.func) # 方法 <bound method A.func of <__main__.A object at 0x00000230BAD4C9E8>>
#### 通过types模块验证
from types import FunctionType # 函数
from types import MethodType # 方法
def func():
pass
class A:
def func(self):
pass
obj = A()
## isinstance(obj,M) 判断 obj对象 ,是不是由M类 或 M类的派生类 实例化的对象
print(isinstance(func,FunctionType)) # True 函数
print(isinstance(A.func,FunctionType)) # True 类调用类中的func 是函数
print(isinstance(obj.func,FunctionType)) # False 实例对象调用 不是函数
print(isinstance(obj.func,MethodType)) # True 实例对象调用 是方法
研究类中的三个特殊的方法(静态方法,类方法,属性)
#### 类中的静态方法是函数(静态函数)
from types import FunctionType
from types import MethodType
class A:
def func(self):
pass